正如主题所说,我希望能够在构建期间运行特定命令,并使其输出成为预处理器宏的定义。
现在,我有几个用户定义的变量(在project.pbxproj中),我可以使用它们的值来填充宏定义,如下所示:
GCC_PREPROCESSOR_DEFINITIONS =(
“字符串(X)= @#X”,
“_MACRO =字符串化($ {MACRO})”,
);
MACRO = foo;
我可以将MACRO设置为每个方案的不同值(例如Debug与Release),这非常有用。但是,我无法弄清楚如何通过运行命令来设置它。
答案 0 :(得分:11)
我可以想到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
或任何其他命令修改现有文件。
自定义构建规则:处理输入文件并创建输出文件的自定义脚本。与运行脚本构建阶段类似,但略好一些,因为只有在修改输入文件时才会运行脚本。例如,创建一个.macro
文件并对其进行处理以更新头文件。
在Xcode中>目标>构建规则,添加新的自定义规则。
流程:*.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
更改时,生成的标头都会更新。
答案 1 :(得分:0)
如果有人好奇,我使用的解决方案是添加一个新的构建阶段,该阶段运行一个脚本,该脚本手动生成带有我想要的宏的头文件。它不优雅,我仍然会更喜欢更好的东西,但它确实有效。
答案 2 :(得分:0)
我认为更好的解决方案是在项目构建设置中声明一个预处理器宏(例如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