2011-10-28 38 views
7

Như chủ đề nói, tôi muốn có thể chạy một lệnh cụ thể trong khi xây dựng, và có đầu ra của nó là định nghĩa của một macro tiền xử lý.với xcode, cách xác định macro tiền xử lý từ đầu ra của lệnh?

Ngay bây giờ, tôi có một vài biến do người dùng định nghĩa (trong project.pbxproj) và tôi có thể sử dụng giá trị của họ để điền vào các định nghĩa vĩ mô, như sau:

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

Tôi có thể đặt MACRO thành giá trị khác cho mỗi lược đồ (ví dụ: Gỡ lỗi và phát hành) rất hữu ích. Nhưng, tôi không thể tìm ra cách để thiết lập nó bằng cách chạy một lệnh.

Trả lời

11

tôi có thể nghĩ đến 3 lựa chọn:

Môi trường biến: Nếu bạn xây dựng từ dòng lệnh bạn có thể xuất một biến (export ENVMACRO=superfoo) trước khi gọi xây dựng lệnh và sử dụng nó trong một tập tin cấu hình Xcode OTHER_CFLAGS=-DMACRO=$(ENVMACRO). Bạn cần định cấu hình mục tiêu với tệp .xcconfig.

Chạy tạo bản dựng giai đoạn: Tập lệnh tùy chỉnh tạo tệp tiêu đề.

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

Trong các thử nghiệm của mình, bạn cần tệp tiêu đề trống để có thể biên dịch chính xác. Có các tùy chọn khác như sửa đổi tệp hiện có bằng cách sử dụng sed hoặc bất kỳ lệnh nào khác.

Quy tắc xây dựng tùy chỉnh: Tập lệnh tùy chỉnh xử lý tệp đầu vào và tạo tệp đầu ra. Tương tự như Chạy tập lệnh pha xây dựng nhưng tốt hơn một chút vì nó sẽ chỉ chạy tập lệnh khi tệp đầu vào đã được sửa đổi. Ví dụ: tạo tệp .macro và xử lý tệp để cập nhật tệp tiêu đề.

Trong Xcode> Nhắm mục tiêu> Quy tắc xây dựng, thêm quy tắc tùy chỉnh mới.

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 file: $(SRCROOT)/Project.h

Project.macro chứa cặp MACRO=one-liner-command.Giống như hai ví dụ không có ý nghĩa:

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

tập tin được tạo ra sẽ giống như sau:

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

Mỗi lần Project.macro thay đổi, tiêu đề được tạo ra sẽ được cập nhật.

+0

cảm ơn - tùy chọn thứ hai về cơ bản là những gì tôi đã làm - trong trường hợp của tôi, tôi muốn lệnh chạy ở mọi công trình. các nếp nhăn duy nhất là tôi không ghi vào tập tin tiêu đề thực tế nếu nội dung của nó không giống với nội dung mới được tạo ra (để tránh sự thay đổi phụ thuộc). tôi đặc biệt thích tùy chọn thứ ba. – michael

0

Nếu có ai tò mò, giải pháp tôi đã sử dụng là thêm giai đoạn xây dựng mới chạy tập lệnh tạo thủ công tệp tiêu đề với các macro mà tôi muốn. Nó không thanh lịch, và tôi vẫn thích cái gì đó tốt hơn, nhưng nó hoạt động.

+1

Chúc mừng giải pháp. Đảm bảo đánh dấu câu trả lời của bạn là 'được chấp nhận' để người khác có thể học hỏi từ thành công của bạn. Chúc mừng ~ –

0

Tôi nghĩ giải pháp tốt hơn là chỉ khai báo một macro tiền xử lý trong cài đặt xây dựng dự án (ví dụ: DEBUG để gỡ lỗi, RELEASE để phát hành) và sau đó trong tệp Prefix.pch bạn có thể kiểm tra giá trị để quyết định các macro khác cần xác định, ví dụ:

// 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 
Các vấn đề liên quan