【问题标题】:with xcode, how to define preprocessor macros from the output of a command?使用 xcode,如何从命令的输出中定义预处理器宏?
【发布时间】:2011-12-17 12:02:05
【问题描述】:

正如主题所说,我希望能够在构建期间运行特定命令,并将其输出作为预处理器宏的定义。

现在,我有几个用户定义的变量(在 project.pbxproj 中),我可以使用它们的值来填充宏定义,如下所示:

GCC_PREPROCESSOR_DEFINITIONS = (
"STRINGIFY(x)=@#x",
"_MACRO=STRINGIFY(${MACRO})",
);
宏 = foo;

我可以将 MACRO 设置为每个方案的不同值(例如调试与发布),这非常有用。但是,我无法弄清楚如何通过运行命令来设置它。

【问题讨论】:

    标签: xcode macros preprocessor


    【解决方案1】:

    如果有人好奇,我使用的解决方案是添加一个新的构建阶段,该阶段运行一个脚本,该脚本手动生成带有我想要的宏的头文件。它并不优雅,我仍然更喜欢更好的东西,但它确实有效。

    【讨论】:

    • 祝贺解决方案。确保将您的答案标记为“已接受”,以便其他人可以从您的成功中学习。干杯~
    【解决方案2】:

    我能想到 3 个选项:

    环境变量:如果您从命令行构建,您可以在调用构建命令之前导出变量 (export ENVMACRO=superfoo) 并在 Xcode 配置文件 OTHER_CFLAGS=-DMACRO=$(ENVMACRO) 中使用它。您需要使用.xcconfig 文件配置目标。

    运行脚本构建阶段:生成头文件的自定义脚本。

    MACROVALUE=$(run-command-to-obtain-value)
    echo "#define MACRO ($MACROVALUE)" > $(SRCROOT)/path/to/header.h
    

    在我的测试中,您需要一个空的头文件才能正确编译。还有其他选项,例如使用 sed 或任何其他命令修改现有文件。

    自定义构建规则:处理输入文件并创建输出文件的自定义脚本。类似于 Run Script 构建阶段,但稍好一些,因为它只会在输入文件被修改时运行脚本。例如,创建一个.macro 文件并对其进行处理以更新一个头文件。

    在 Xcode > Target > Build rules 中,添加新的自定义规则。

    进程*.macro

    自定义脚本:

    HEADER="${SRCROOT}/Config.h"
    cd ${SRCROOT}
    echo "// Do not edit" > $HEADER
    cat "${INPUT_FILE_PATH}" | while read line
    do
        macro="`echo $line | cut -d= -f1`"
        cmd="`echo $line | cut -d= -f2-`"
        value=$($cmd)
        echo "#define ${macro} @\"${value}\"" >> $HEADER
    done
    echo "// Updated on "`date` >> $HEADER
    

    输出文件$(SRCROOT)/Project.h

    Project.macro 包含对 MACRO=one-liner-command。就像这两个无意义的例子:

    COMMIT=git log --pretty=format:%h -n 1
    BUILDYEAR=date +%Y
    

    生成的文件如下所示:

    // Do not edit
    #define COMMIT @"c486178"
    #define BUILDYEAR @"2011"
    // Updated on Sat Oct 29 14:40:41 CEST 2011
    

    每次Project.macro 更改时,生成的标头都会更新。

    【讨论】:

    • 谢谢——第二个选项本质上就是我所采用的——就我而言,我希望该命令在每次构建时都运行。唯一的问题是,如果实际头文件的内容与新生成的内容不同(以避免依赖关系更改),我不会写入实际的头文件。我也特别喜欢第三种选择。
    【解决方案3】:

    我认为更好的解决方案是在项目构建设置中仅声明一个预处理器宏(例如,DEBUG 用于调试,RELEASE 用于发布),然后在 Prefix.pch 文件中检查值为了决定要定义哪些其他宏,例如:

    // Use NSLOG and NSASSERT so that they are only output in debug mode
    #ifdef DEBUG
    
    //#warning You are running in Debug mode
    #define NSLOG NSLog
    #define NSASSERT NSAssert
    #define NSASSERT1 NSAssert1
    
    #else
    
    #define NSLOG if(false)NSLog
    #define NSASSERT(X, Y)  \
    if(!(X)) {          \
    NSLogOkay(Y);       \
    }                   
    #define NSASSERT1(X, Y, Z)  \
    if(!(X)) {              \
    NSLogOkay(Y, Z);        \
    }                       
    
    #endif
    

    【讨论】:

      猜你喜欢
      • 2021-12-29
      • 2011-12-12
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 2016-12-14
      相关资源
      最近更新 更多