C 扩充现有的Makefile

C 扩充现有的Makefile,c,makefile,autotools,configure,autoconf,C,Makefile,Autotools,Configure,Autoconf,我正在开发一个依赖于C库的现有程序,实际上这是一个相当旧的程序,它只是有一个Makefile和一个README文件,其中包含一些修改Makefile以在不同系统上成功编译的指令。我的任务是清理程序的构建过程,使其可移植,而无需修改makefile等,因此这意味着确保C库是可移植的 例如,在最新版本的MacOS上需要做的一件事是正确定义SIZEOF\u VOID\p,因为如果未定义,它默认为4,这自然会在64位系统上导致可怕的分段故障。我刚刚在Makefile中将其定义为8,但显然现在我已经将其用

我正在开发一个依赖于C库的现有程序,实际上这是一个相当旧的程序,它只是有一个
Makefile
和一个
README
文件,其中包含一些修改Makefile以在不同系统上成功编译的指令。我的任务是清理程序的构建过程,使其可移植,而无需修改makefile等,因此这意味着确保C库是可移植的

例如,在最新版本的
MacOS
上需要做的一件事是正确定义
SIZEOF\u VOID\p
,因为如果未定义,它默认为
4
,这自然会在64位系统上导致可怕的分段故障。我刚刚在Makefile中将其定义为8,但显然现在我已经将其用于32位系统

我最初的想法是编写一个C文件,该文件的输出包含一些
#ifdef
s,如果它们缺少一个输出到现有makefile的前置词,则会给出相应的定义,但这似乎有点粗糙。不管怎样,标准配置脚本似乎都是自己完成的,所以我想为什么不使用它们呢。我了解到可以使用
autoconf
生成配置脚本,但我不想丢弃现有的makefile(我担心这可能会导致比解决问题更多的问题)。我只是想给它们添加一些合适的定义


有什么好办法吗?

如果
autoconf
cmake
或类似的程序不是一个选项,那么您可以做一些类似于您自己想法的事情

CC=gcc
冒牌货:全部
全部:主要
预构建:
$(CC)常数.c-o常数
$(eval SIZEOF\u VOID\u P=$(shell./常量“SIZEOF\u VOID\u P”))
$(eval FOOBAR=$(shell./常量“FOOBAR”))
主要内容:预构建
@echo$(SIZEOF\u VOID\u 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);
}
#包括
#包括
#包括
//所有的制衡都省略了!
int main(int argc,字符**argv){
如果(argc!=2){
fprintf(stderr,“用法:%s常量到测试”,argv[0]);
退出(退出失败);
}
//适用于几个常量,但应进行更改
//如果你有十几个以上的解析器
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);
}
// ...
否则{
fprintf(stderr,“常量%s未知”,argv[1]);
退出(退出失败);
}
退出(退出成功);
}
到目前为止,它不是最优雅的解决方案,但如果您只需要一些常量,它就可以很好地工作。另一方面:对于更复杂的事情,它会很快变得非常糟糕,例如:找到正确编译器的路径并使用正确的参数调用它,找到一些库的路径并检查它们是否正确,等等

我不想丢弃现有的makefile(我担心这可能会导致比它解决的问题更多的问题)。我只是想给它们添加一些合适的定义

这有什么好办法吗

如果您准备假设GNU make,那么您可以依赖它的
include
指令将外部文件中的Makefile片段包含到现有的Makefile中。您可以修改现有的makefile,在顶部或附近添加一个或多个
include
指令,以代替需要调整以适应生成环境的部分。然后编写一个程序来分析系统,并将适当的Make变量定义输出到适当的文件中。但是,
include
指令不是POSIX
make
的标准功能,因此它可能不是一个可行的选项


或者,可以在命令行上指定
make
变量定义。比如说,

make all SIZEOF_VOID_P=8

原则上,您可以通过以这种方式提供定义的包装器脚本调用
make
,来设置所需的所有make变量。这样的脚本可以动态地确定所需的值,也可以通过单独的配置程序生成脚本。无论采用哪种方式,您都可能需要修改现有的makefile以禁止(重新)定义所涉及的变量。

更改代码,使其使用
sizeof(void*)
而不是
sizeof\u void\p
?C库不是我的,如果我能正确定义宏,我宁愿不去修改它的所有代码。如果它是旧的、未维护的,你也可以接管它的副本(假设它是开源的)。使用自定义版本的库的主要问题是,您可能会发现很难将您的更改与上游更改合并,但是如果没有上游更改,那么您就没有这个问题。(您也不能将它们作为.so文件分发,因为用户可能有不同的非自定义版本)我给出的示例不是唯一的问题,因此还有关于配置脚本的问题。这些定义目前来自哪里?makefile提供了它们,还是它们在头文件中?该makefile不起作用,因为
SIZEOF\u VOID\u P=$(shell./constants SIZEOF\u VOID\u P)
是配方的一部分,因此不会在规则中持续存在。。。您需要一个
eval
来设置变量…@John makefile按原样工作,但您是对的,当然,它只按原样工作,并经过GNU make 3.81版的测试。你认为你的评论够了吗?或者我应该把这些信息编入我的答案和/或改变这个例子吗?但我会再等几个小时,等待OP给出一些反馈,还有更多需要更改/调整的可能性。我刚刚尝试过它(使用make 3.81),结果发现
make:SIZEOF\u VOID\u P:Command未找到
。我可能会用eval更新它。@johnyepp,我也是。现在!我发誓它昨天起作用了!什么。。。?C&P错误?哦,天哪,多尴尬啊!sign改为
eval
,并在helper pr的参数周围加上引号