Skip to content

Switch the CMake in pico-blink-sdk+pico-w-blink-sdk to use CMake native Swift support #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion harmony/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ The firmware for Harmony is built using CMake and requires the Raspberry Pi Pico

4. Generate the build files using CMake:
```bash
cmake -B build -G Ninja .
cmake -B build -G Ninja . -DCMAKE_EXPORT_COMPILE_COMMANDS=On
```

5. Build the firmware:
Expand Down
90 changes: 49 additions & 41 deletions pico-blink-sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.29)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

set(CMAKE_Swift_COMPILATION_MODE wholemodule)
set(CMAKE_Swift_COMPILER_WORKS YES)

project(swift-blinky)
pico_sdk_init()

if(APPLE)
execute_process(COMMAND xcrun -f swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
execute_process(COMMAND which swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
enable_language(Swift)

set(SWIFT_TARGET "armv6m-none-none-eabi") # default for rp2040

if(PICO_PLATFORM STREQUAL "rp2350-arm-s")
message(STATUS "PICO_PLATFORM is set to rp2350-arm-s, using armv7em")
set(SWIFT_TARGET "armv7em-none-none-eabi")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-mfloat-abi=soft")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -mfloat-abi=soft")
elseif(PICO_PLATFORM STREQUAL "rp2040")
message(STATUS "PICO_PLATFORM is set to RP2040, using armv6m")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-mfloat-abi=soft")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -mfloat-abi=soft")
elseif(PICO_PLATFORM STREQUAL "rp2350-riscv")
message(STATUS "PICO_PLATFORM is set to rp2350-riscv, using riscv32.")
set(SWIFT_TARGET "riscv32-none-none-eabi")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-march=rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb" "-Xcc" "-mabi=ilp32")
list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -march=rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb -Xcc -mabi=ilp32")
endif()

add_executable(swift-blinky)
add_executable(swift-blinky
# Source files:
Main.swift
)

set_target_properties(swift-blinky PROPERTIES LINKER_LANGUAGE CXX)

target_link_libraries(swift-blinky
pico_stdlib hardware_uart hardware_gpio
)

# Gather compile definitions from all dependencies
# Clear the default COMPILE_OPTIONS which include C specific compiler flags that the Swift compiler will not accept
# Instead, set those options to only apply when compiling C code.
set_target_properties(pico_standard_link PROPERTIES INTERFACE_COMPILE_OPTIONS "")
target_compile_options(pico_standard_link INTERFACE "$<$<COMPILE_LANGUAGE:C>:SHELL: -ffunction-sections -fdata-sections>")

# Gather C compile definitions from all dependencies
set_property(GLOBAL PROPERTY visited_targets "")
set_property(GLOBAL PROPERTY compilerdefs_list "")

Expand All @@ -42,20 +49,18 @@ function(gather_compile_definitions_recursive target)

# make sure we don't visit the same target twice
# and that we don't visit the special generator expressions
if (${target} MATCHES "\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
if (${target} MATCHES "\\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
return()
endif()

# Append the target to visited_targets
list(APPEND visited_targets ${target})
set_property(GLOBAL PROPERTY visited_targets "${visited_targets}")

# Get the current value of compilerdefs_list
get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)

get_target_property(target_definitions ${target} INTERFACE_COMPILE_DEFINITIONS)
if (target_definitions)
# Append the target definitions to compilerdefs_list
get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
list(APPEND compilerdefs_list ${target_definitions})
set_property(GLOBAL PROPERTY compilerdefs_list "${compilerdefs_list}")
endif()
Expand All @@ -71,35 +76,38 @@ endfunction()

gather_compile_definitions_recursive(swift-blinky)
get_property(COMPILE_DEFINITIONS GLOBAL PROPERTY compilerdefs_list)
get_property(INCLUDES GLOBAL PROPERTY includes_list)

# Parse compiler definitions into a format that swiftc can understand
# Convert compiler definitions into a format that swiftc can understand
list(REMOVE_DUPLICATES COMPILE_DEFINITIONS)
list(PREPEND COMPILE_DEFINITIONS "")
list(PREPEND COMPILE_DEFINITIONS "") # adds a semicolon at the beginning
string(REPLACE "$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>" "$<TARGET_PROPERTY:swift-blinky,PICO_TARGET_BINARY_TYPE>" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
string(REPLACE ";" ";-Xcc;-D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
COMMAND
${SWIFTC}
-target ${SWIFT_TARGET} -Xcc -fshort-enums
${COMPILE_DEFINITIONS}
string(REPLACE ";" " -Xcc -D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")

# Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header).
set(IMPLICIT_INCLUDES)
foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
endforeach()
foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
endforeach()

target_compile_options(swift-blinky PUBLIC
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:
-target ${SWIFT_TARGET}
-enable-experimental-feature Embedded
-parse-as-library
-module-name swift_blinky

${CLANG_ARCH_ABI_FLAGS}
-Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library
$$\( echo '$<TARGET_PROPERTY:swift-blinky,INCLUDE_DIRECTORIES>' | tr '\;' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
$$\( echo '${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}' | tr ' ' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
-Xcc -fshort-enums
-Xfrontend -function-sections
-import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
${CMAKE_CURRENT_LIST_DIR}/Main.swift
-c -o ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
DEPENDS
${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
${CMAKE_CURRENT_LIST_DIR}/Main.swift
)
add_custom_target(swift-blinky-swiftcode DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o)

${COMPILE_DEFINITIONS}
${IMPLICIT_INCLUDES}
>")

target_link_libraries(swift-blinky
${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
)
add_dependencies(swift-blinky swift-blinky-swiftcode)
pico_add_extra_outputs(swift-blinky)
2 changes: 1 addition & 1 deletion pico-blink-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ $ export PICO_BOARD='<board-name>' # Examples: pico, pico2
$ export PICO_PLATFORM='<optional-platform-name>' # Optional; useful if you'd like to compile for RISC-V. Examples: rp2040, rp2350-arm-s, rp2350-riscv
$ export PICO_SDK_PATH='<path-to-your-pico-sdk>'
$ export PICO_TOOLCHAIN_PATH='<path-to-the-compiler-toolchain>' # A default `brew` install will be located at `/Applications/ArmGNUToolchain/[version]/arm-none-eabi`. This can also be a RISC-V toolchain for the RP2350.
$ cmake -B build -G Ninja .
$ cmake -B build -G Ninja . -DCMAKE_EXPORT_COMPILE_COMMANDS=On
$ cmake --build build
```

Expand Down
83 changes: 45 additions & 38 deletions pico-w-blink-sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
cmake_minimum_required(VERSION 3.13)
cmake_minimum_required(VERSION 3.29)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

set(CMAKE_Swift_COMPILATION_MODE wholemodule)
set(CMAKE_Swift_COMPILER_WORKS YES)

project(swift-blinky)
pico_sdk_init()
enable_language(Swift)

add_executable(swift-blinky
# Source files:
Main.swift
)

if(APPLE)
execute_process(COMMAND xcrun -f swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
execute_process(COMMAND which swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
set_target_properties(swift-blinky PROPERTIES LINKER_LANGUAGE CXX)

add_executable(swift-blinky)
target_link_libraries(swift-blinky
pico_stdlib hardware_uart hardware_gpio pico_lwip_arch pico_cyw43_arch_none
)

# Gather compile definitions from all dependencies
# Clear the default COMPILE_OPTIONS which include C specific compiler flags that the Swift compiler will not accept
# Instead, set those options to only apply when compiling C code.
set_target_properties(pico_standard_link PROPERTIES INTERFACE_COMPILE_OPTIONS "")
target_compile_options(pico_standard_link INTERFACE "$<$<COMPILE_LANGUAGE:C>:SHELL: -ffunction-sections -fdata-sections>")

# Gather C compile definitions from all dependencies
set_property(GLOBAL PROPERTY visited_targets "")
set_property(GLOBAL PROPERTY compilerdefs_list "")

Expand All @@ -25,20 +34,18 @@ function(gather_compile_definitions_recursive target)

# make sure we don't visit the same target twice
# and that we don't visit the special generator expressions
if (${target} MATCHES "\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
if (${target} MATCHES "\\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
return()
endif()

# Append the target to visited_targets
list(APPEND visited_targets ${target})
set_property(GLOBAL PROPERTY visited_targets "${visited_targets}")

# Get the current value of compilerdefs_list
get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)

get_target_property(target_definitions ${target} INTERFACE_COMPILE_DEFINITIONS)
if (target_definitions)
# Append the target definitions to compilerdefs_list
get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
list(APPEND compilerdefs_list ${target_definitions})
set_property(GLOBAL PROPERTY compilerdefs_list "${compilerdefs_list}")
endif()
Expand All @@ -54,37 +61,37 @@ endfunction()

gather_compile_definitions_recursive(swift-blinky)
get_property(COMPILE_DEFINITIONS GLOBAL PROPERTY compilerdefs_list)
get_property(INCLUDES GLOBAL PROPERTY includes_list)

# Parse compiler definitions into a format that swiftc can understand
# Convert compiler definitions into a format that swiftc can understand
list(REMOVE_DUPLICATES COMPILE_DEFINITIONS)
list(PREPEND COMPILE_DEFINITIONS "") # adds a semicolon at the beginning
string(REPLACE "$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>" "$<TARGET_PROPERTY:swift-blinky,PICO_TARGET_BINARY_TYPE>" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
string(REPLACE ";" ";-Xcc;-D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
string(REPLACE ";" " -Xcc -D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")

add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
COMMAND
${SWIFTC}
-target armv6m-none-none-eabi -Xcc -mfloat-abi=soft -Xcc -fshort-enums
${COMPILE_DEFINITIONS}
-Xcc -DCYW43_LWIP
-Xcc -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND
-Xcc -I$ENV{PICO_SDK_PATH}/lib/lwip/src/include
-Xcc -I${CMAKE_CURRENT_LIST_DIR}/include
-Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library
$$\( echo '$<TARGET_PROPERTY:swift-blinky,INCLUDE_DIRECTORIES>' | tr '\;' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
$$\( echo '${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}' | tr ' ' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
# Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header).
set(IMPLICIT_INCLUDES)
foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
endforeach()
foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
endforeach()

target_compile_options(swift-blinky PUBLIC
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:
-target armv6m-none-none-eabi
-enable-experimental-feature Embedded
-parse-as-library
-module-name swift_blinky

-Xcc -fshort-enums
-Xfrontend -function-sections
-import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
${CMAKE_CURRENT_LIST_DIR}/Main.swift
-c -o ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
DEPENDS
${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
${CMAKE_CURRENT_LIST_DIR}/Main.swift
)
add_custom_target(swift-blinky-swiftcode DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o)
${COMPILE_DEFINITIONS}
${IMPLICIT_INCLUDES}
>")

target_link_libraries(swift-blinky
${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
)
add_dependencies(swift-blinky swift-blinky-swiftcode)
pico_add_extra_outputs(swift-blinky)
2 changes: 1 addition & 1 deletion pico-w-blink-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ $ export TOOLCHAINS='<toolchain-identifier>'
$ export PICO_BOARD=pico_w
$ export PICO_SDK_PATH='<path-to-your-pico-sdk>'
$ export PICO_TOOLCHAIN_PATH='<path-to-the-arm-toolchain>'
$ cmake -B build -G Ninja .
$ cmake -B build -G Ninja . -DCMAKE_EXPORT_COMPILE_COMMANDS=On
$ cmake --build build
```

Expand Down
Loading