我正在研究一个现有的程序,它依赖于一个C库,一个相当古老的C,它有一个Makefile和一个README文件,它有一些修改Mag文件的指令,以便在不同的系统上成功编译。我的任务是清理程序的构建过程,这样就可以在不攻击makefile等的情况下进行移植,这意味着确保C库是可移植的。
例如,在最新版本的MacOS上需要做的一件事是正确定义SIZEOF_VOID_P,因为如果未定义,则默认为4,这自然会在64位系统上导致可怕的segfaults。我刚刚在Makefile中将其定义为8,但显然现在我已经为32位系统断开了它。
我的想法最初只是写一个C文件,它的输出有一些#ifdef s,如果他们缺少一个输出到现有的MaCfile文件的预置,就吐出适当的定义,但是它看起来有点古怪。无论如何,标准配置脚本似乎都是自己完成的,所以我想为什么不使用它们。我读到,可以用autoconf生成配置脚本,但我不想废掉现有的生成文件(我担心它可能会导致比它解决的更多的问题)。我只想给它们加上一些适当的定义。
有什么好的原因吗?

最佳答案

如果autoconfcmake或类似的程序不是一个选项,您可以做一些与您自己的想法类似的事情。

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);
}

它不是最优雅的解决方案,但如果您只需要一些常量,它就可以很好地工作。另一方面:对于更复杂的事情,例如:找到正确编译器的路径并用正确的参数调用它,找到某些库的路径并检查它们是否正确,等等,它会很快变得相当糟糕。

09-26 22:20