Search code examples
cmakemetalmetalkit

Building metallib with CMake


I have some .metal files and I want to compile it to .metallib. Whole build system is using CMake and I am going to use it to compile .metal too.

To build .metallib I must use the next two commands:

xcrun -sdk macosx metal -c MyLibrary.metal -o MyLibrary.air
xcrun -sdk macosx metallib MyLibrary.air -o MyLibrary.metallib

Is there any convenient way to do it with CMake where I can set compiler and CMake will do everything automatically? Or I should use add_custom_command and manually call xcrun?


Solution

  • TL;DR Both approaches, using custom commands/targets and adding a new language, are valid. The choice seems to depend on trade-offs between reusability, distribution range, target users, etc. Personally, I'd initially opt for the former.


    Having said that, if you opt for the add_custom_command/add_custom_target method, it can get you pretty far. Just make sure that you provide actual targets and link them with the OUTPUT of custom commands, in order to be able to set up proper dependencies and avoiding unnecessary re-execution of targets when dependencies are still up to date. For example,

    set(FOO_FILE "foo.txt")
    
    add_custom_command(OUTPUT ${FOO_FILE}
      COMMAND ${CMAKE_COMMAND} -E touch ${FOO_FILE}
      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
      COMMENT "Creating ${FOO_FILE}"
      VERBATIM)
    
    add_custom_target(foo DEPENDS ${FOO_FILE})
    

    The approach of adding a new language is a bit more involved, as it's targeted to be more generic and provide language support as a CMake feature (i.e. not tied to a particular project). For this, you are required to define various aspects of the language, such as the compiler and the rules to use to process the source files. Apart, from these, feature detection and testing usually fall here too. For more detailed documentation have a look here.

    However, investigating an actual language as is supported by CMake could be helpful. I'd suggest having a look under CMake's Modules directory for CUDA (this will lead you to have a look into the Compiler and Platform subdirs too).

    NOTE: Digging through the mailing list, I bumped into this thread, that mentions that the second approach might not work so well with non Makefile-based generators. It is not clear from the thread (or the existing documentation) and I cannot try it since I'm not using CMake via such a tool (e.g. MSVC or Xcode).