Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

with xcode, how to define preprocessor macros from the output of a command?

As the topic says, I want to be able to run a specific command during build, and have its output be the definition of a preprocessor macro.

Right now, I have several user-defined variables (in project.pbxproj) and I am able to use their values to fill macro definitions, as follows:

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

I can set MACRO to a different value per scheme (e.g Debug vs. Release) which is very useful. But, I cannot figure out how to set it by running a command.

like image 842
michael Avatar asked Oct 28 '11 18:10

michael


People also ask

What is preprocessor macros in Xcode?

Preprocessor Macros are directives executed by the compiler, so they're not part of Objective C. We've used them many times before with the #import statement. But to stay with our Lite and Pro example: you can use a Preprocessor if/then statement to check which version is being compiled.

What is preprocessor in Objective C?

The Objective-C Preprocessor is not part of the compiler, but is a separate step in the compilation process. In simplistic terms, an Objective-C Preprocessor is just a text substitution tool and it instructs compiler to do required pre-processing before actual compilation.


1 Answers

I can think of 3 options:

Environment variable: If you build from command line you can export a variable (export ENVMACRO=superfoo) before invoking the build command and use it in an Xcode configuration file OTHER_CFLAGS=-DMACRO=$(ENVMACRO). You need to configure the target with the .xcconfig file.

Run Script Build Phase: Custom script that generates a header file.

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

In my tests you need an empty header file to be able to compile properly. There are other options like modifying an existing file using sed or any other command.

Custom Build Rule: Custom script that process an input file and creates an output file. Similar to Run Script build phase but slightly better because it will run the script only when the input file has been modified. For example, create a .macro file and process it to update a header file.

In Xcode > Target > Build rules, add new custom rule.

Process: *.macro

Custom script:

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

Output files: $(SRCROOT)/Project.h

Project.macro contains pairs MACRO=one-liner-command. Like these two non-sense examples:

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

Generated file will look like:

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

Each time Project.macro changes, the generated header will be updated.

like image 163
djromero Avatar answered Oct 11 '22 11:10

djromero