|
| 1 | +# Stringify Macro Example |
| 2 | + |
| 3 | +This project demonstrates building and using a Swift macro in CMake. |
| 4 | + |
| 5 | +## Requirements |
| 6 | + - Swift 5.9 (5.9.0+ macOS, 5.9.1 Windows and Linux) |
| 7 | + |
| 8 | +## Build Instructions |
| 9 | + |
| 10 | +```sh |
| 11 | +> mkdir build && cd build |
| 12 | +> cmake -G 'Ninja' ../ |
| 13 | +> ninja |
| 14 | +> ./HelloMacros |
| 15 | +(4, "1 + 3") |
| 16 | +``` |
| 17 | + |
| 18 | +## Description |
| 19 | + |
| 20 | +Macros must build for the local machine doing the building, not the machine |
| 21 | +you're building for because the compiler executes them. It's important to |
| 22 | +consider the macro as a separate project from the main part of the codebase if |
| 23 | +there is any chance you will want to cross-compile the project. |
| 24 | + |
| 25 | +We can manually invoke CMake twice, once to build the macro, then again to build |
| 26 | +the actual project for whatever platform we're building for, but that isn't very |
| 27 | +convenient. Instead, we use `ExternalProject_Add` to include the macro project |
| 28 | +which invokes compile |
| 29 | + |
| 30 | +```cmake |
| 31 | +ExternalProject_Add(StringifyMacro |
| 32 | + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/StringifyMacro" |
| 33 | + INSTALL_COMMAND "") |
| 34 | +ExternalProject_Get_Property(StringifyMacro BINARY_DIR) |
| 35 | +string(StringifyMacroPath "${BINARY_DIR}/StringifyMacro#StringifyMacro") |
| 36 | +``` |
| 37 | + |
| 38 | +Technically, neither the compiler nor CMake know the triple for the build |
| 39 | +machine. This is normal, but inconvenient. We are assuming that the Swift |
| 40 | +compiler is configured to compile for the build machine by default. |
| 41 | +`ExternalProject_Add` doesn't forward variables from the current project into |
| 42 | +the external project, which is normally a pain-point of external projects, but |
| 43 | +in this case, is exactly what we want. |
| 44 | + |
| 45 | +In the macro project, we need to import SwiftSyntax to access the macro |
| 46 | +libraries. Since SwiftSyntax and the macro are built to run in the same |
| 47 | +environment, we can use `FetchContent` to merge the build graphs and build the |
| 48 | +entire macro project as one. |
| 49 | +```cmake |
| 50 | +FetchContent_Declare(SwiftSyntax |
| 51 | + GIT_REPOSITORY https://github.com/apple/swift-syntax.git |
| 52 | + GIT_TAG 247e3ce379141f81d56e067fff5ff13135bd5810) |
| 53 | +FetchContent_MakeAvailable(SwiftSyntax) |
| 54 | +``` |
| 55 | + |
| 56 | +Then it's just a matter of linking our macro executable against the needed |
| 57 | +libraries. |
| 58 | + |
| 59 | +```cmake |
| 60 | +add_executable(StringifyMacro macro.swift) |
| 61 | +target_compile_options(StringifyMacro PRIVATE -parse-as-library) |
| 62 | +target_link_libraries(StringifyMacro |
| 63 | + SwiftSyntax |
| 64 | + SwiftSyntaxMacros |
| 65 | + SwiftCompilerPlugin) |
| 66 | +``` |
0 commit comments