开发者

How can I set up an Xcode build rule with a variable output file list?

开发者 https://www.devze.com 2023-02-13 14:49 出处:网络
Build Rules are documented in the Xcode Build System Guide They are well adapted to the common case where one input file is transformed into a fixed number (usually one) of output files.

Build Rules are documented in the Xcode Build System Guide

They are well adapted to the common case where one input file is transformed into a fixed number (usually one) of output files.

The output files must be described in the "Output Files" area of the build rule definition; one line per output file. Typically the output files have the same name as the input file but have different extensions.

In my case, one single input file is transformed into a variable number of files with the same extensions. The number and the names of the output files depend on the content of the input file and are not known in advance.

The output files will have to be further processed later on (they are in this case C files to be compiled).

How can I set up a build rule for such a case?

Any suggestions welcome.

(I asked the same question on the Apple developer forum, but I figured 开发者_StackOverflow中文版it'd be a good idea to ask here too).


I dealt with this by, instead of generating multiple C files, just concatenating them all together into one file (e.g. "AUTOGENERATED.c"), and specifying that as the output file.

So long as your output files don't contain anything that will conflict (static functions with the same name, conflicting #defines etc.) this works well.


See this article on Cocoa With Love:
http://cocoawithlove.com/2010/02/custom-build-rules-generated-tables-and.html

This has an example of generating custom C code and using that as input to the normal build process. He's using ${} variable syntax in the output


The best way I found to add any number of files to my xcode project (and make some processing) is to write a little php script. The script can simply copy files into the bundle. The tricky part is the integration with xcode. It took me some time to find a clean way. (You can use the script language you like with this method).

First, use "Add Run Script" instead of "Add Copy File"

Shell parameter:

/bin/sh

Command parameter:

${SRCROOT}/your_script.php -s ${SRCROOT} -o ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
exit $?

(screenshot in xcode)

${SRCROOT} is your project directory.

${CONFIGURATION(...) is the bundle directory. Exactly what you need :)

This way, your script return code can stop xcode build (use die(0) for success and die(1) for failures) and the output of script will be visible in xcode's build log.

Your script will look like that: (don't forget chmod +x on it)

#!/usr/bin/php
<?php
error_reporting(E_ALL);
$options = getopt("s:o:");
$src_dir = $options["s"]."/";
$output_dir = $options["o"]."/";

// process_files (...)

die(0);
?>

BONUS: here my 'add_file' function.

  • Note the special treatment for PNG (use apple's png compression)
  • Note the filemtime/touch usage to prevent copy files each times.

l

define("COPY_PNG", "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/copypng -compress");
function add_file_to_bundle($output_dir, $filepath) {

    // split path
    $path_info = pathinfo($filepath);
    $output_filepath = $output_dir.$path_info['basename'];

    // get file's dates of input and output
    $input_date = filemtime($filepath);
    $output_date = @filemtime($output_filepath);

    if ($input_date === FALSE) { echo "can't get input file's modification date"; die(1); }

    // skip unchanged files
    if ($output_date === $input_date) {

            //message("skip ".$path_info['basename']);
            return 0;
    }

    // special copy for png with apple's png compression tool
    if (strcasecmp($path_info['extension'], "png") == 0) {

            //message($path_info['basename']." is a png");
            passthru(COPY_PNG." ".escapeshellarg($filepath)." ".escapeshellarg($output_filepath), $return_var);
            if ($return_var != 0) die($return_var);
    }
    // classic copy
    else {

            //message("copy ".$path_info['basename']);
            passthru("cp ".escapeshellarg($filepath)." ".escapeshellarg($output_filepath), $return_var);
            if ($return_var != 0) die($return_var);
    }

    // important: set output file date with input file date
    touch($output_filepath, $input_date, $input_date);
    return 1;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号