2011-10-28 13 views
7

Zgodnie z tematem, chcę mieć możliwość uruchomienia określonego polecenia podczas kompilacji, a jego wyjście powinno być definicją makra preprocesora.z xcode, jak zdefiniować makra preprocesora z wyjścia polecenia?

Teraz mam kilka zmiennych zdefiniowanych przez użytkownika (w project.pbxproj) i jestem w stanie wykorzystać swoje wartości do wypełnienia definicji makr, co następuje:

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

Mogę ustawić MACRO na inną wartość na schemat (np. Debug vs. Release), co jest bardzo przydatne. Ale nie wiem, jak to ustawić, wykonując polecenie.

Odpowiedz

11

mogę myśleć z 3 opcji:

Środowisko zmienna: Jeśli budować z linii poleceń można wyeksportować zmienną (export ENVMACRO=superfoo) przed wywołaniem polecenia kompilacji i użyć go w pliku konfiguracyjnym Xcode OTHER_CFLAGS=-DMACRO=$(ENVMACRO). Musisz skonfigurować cel za pomocą pliku .xcconfig.

Wykonaj skrypt Utwórz fazę: Niestandardowy skrypt, który generuje plik nagłówkowy.

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

W moich testach potrzebny jest pusty plik nagłówkowy, aby można było poprawnie skompilować. Istnieją inne opcje, takie jak modyfikowanie istniejącego pliku za pomocą sed lub dowolne inne polecenie.

Reguła niestandardowego budowania: Skrypt niestandardowy przetwarzający plik wejściowy i tworzący plik wyjściowy. Podobny do Wykonaj skrypt fazie budowy, ale nieco lepiej, ponieważ uruchomi skrypt tylko wtedy, gdy plik wejściowy został zmodyfikowany. Na przykład utwórz plik .macro i przetwórz go, aby zaktualizować plik nagłówkowy.

W Xcode> Cel> Ustal reguły, dodaj nową regułę niestandardową.

Process: *.macro

Niestandardowy skrypt:

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 

Pliki wyjściowe: $(SRCROOT)/Project.h

Project.macro zawiera pary MACRO=one-liner-command.Podobnie jak te dwa przykłady nie sensie

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

Wygenerowany plik będzie wyglądać następująco:

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

Każdy czas Project.macro zmiany wygenerowany nagłówek zostanie zaktualizowany.

+0

dzięki - druga opcja jest w zasadzie tym, co zrobiłem - w moim przypadku chciałem, aby polecenie działało przy każdej kompilacji. jedyną wadą jest to, że nie piszę do faktycznego pliku nagłówkowego, jeśli jego zawartość nie jest identyczna z nowo wygenerowaną zawartością (aby uniknąć zmiany zależności). Szczególnie podoba mi się również trzecia opcja. – michael

0

Jeśli ktoś jest ciekawy, rozwiązaniem, którego użyłem, jest dodanie nowej fazy kompilacji, która uruchamia skrypt, który ręcznie generuje plik nagłówkowy z żądanymi makrami. To nie jest eleganckie, a ja wolałbym jeszcze coś lepszego, ale działa.

+1

Gratulujemy rozwiązania. Zaznacz swoją odpowiedź jako "zaakceptowaną", aby inni mogli uczyć się na Twoim sukcesie. Pozdrowienia ~ –

0

Myślę, że lepszym rozwiązaniem byłoby zadeklarowanie tylko jednego makra preprocesora w ustawieniach budowania projektu (np. DEBUG dla debugowania, RELEASE do wydania), a następnie w pliku Prefix.pch można sprawdzić wartość, aby zdecydować jakie inne makra do zdefiniowania, np .:

// 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 
Powiązane problemy