xcodecmakegenerated-code

CMake: generate and compile architecture-specific source files in XCode


I have a CMake project that's used to generate an iOS-targeted XCode project that supports multiple CPU architectures (arm64 and armv7).

My CMake project includes some commands (defined with add_custom_command) that convert Lua scripts into C++ source files. These generated C++ files differ by architecture (the armv7 file should not be compiled for arm64 and vice versa). The tool meant to be invoked like this:

./data_tool --input <script> --output <C++ source> --architecture <armv7 or arm64>

My (incorrect) CMake file currently looks something like this:

foreach(ARCHITECTURE ${TARGET_ARCHITECTURES})
        string(
            REPLACE ".lua" ".cpp" GENERATED_CPP
            ${GENERATED_SOURCE_DIRECTORY}/${ARCHITECTURE}/${INPUT_SCRIPT}
        )

        add_custom_command(
                    OUTPUT ${GENERATED_CPP}
                    COMMAND ${DATA_TOOL} --input "${INPUT_SCRIPT}" --output "${GENERATED_CPP}" --architecture ${ARCHITECTURE}
                    MAIN_DEPENDENCY ${INPUT_SCRIPT}
        )
        list( APPEND GENERATED_SOURCE ${GENERATED_CPP} )
endforeach()

Later, GENERATED_SOURCE is appended to the source file list passed to add_executable. This code is obviously wrong because both the armv7 and arm64 files are compiled when building for either architecture.

How can I tell CMake that each architecture compiles a different set of source files?


Solution

  • XCode doesn't have a great way to exclude files based on the architecture being built. While it is possible (see Disabling some files in XCode project from compilation), setting this up via CMake is going to be somewhat difficult.

    Instead, I would suggest simply making your generation tool/script put preprocessor guards around the entire file, for the architecture that the generated file supports. That way, when XCode compiles them, they will be essentially empty, except for the architecture that they are meant for. In this answer (Determine if the device is ARM64), it shows how you can do a conditional compile based on arm64 (and use the reverse for armv7).