Skip to content

Commit

Permalink
Allow building macOS client with Makefiles
Browse files Browse the repository at this point in the history
This removes the strict requirement to use the Xcode project generator,
but still requires the Xcode build tools (and specifically the Metal
compiler) to be installed.

I expect that our official stance will always be that the Xcode project
generator is the recommended and supported way to do macOS builds, but
any day I don't have to launch Xcode is a good day.
  • Loading branch information
dpogue committed Aug 7, 2024
1 parent 2a60d41 commit 7ce9730
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 51 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ if(POLICY CMP0127)
endif()

include(CMakeDependentOption)
include(FeatureSummary)
include(Dependencies)
include(FeatureSummary)
include(MetalShaderSupport)
include(VcpkgToolchain)

project(Plasma)
Expand Down Expand Up @@ -161,6 +162,7 @@ endif(PLASMA_PIPELINE_GL)

if(PLASMA_PIPELINE_METAL)
add_definitions(-DPLASMA_PIPELINE_METAL)
enable_language(Metal)
endif(PLASMA_PIPELINE_METAL)

# Allow us to disable certain parts of the build
Expand Down
16 changes: 7 additions & 9 deletions Sources/Plasma/Apps/plClient/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ elseif(APPLE)
Mac-Cocoa/PLSLoginWindowController.xib
Mac-Cocoa/PLSPatcherWindowController.xib
)
list(APPEND plClient_SHADERTARGETS
pfMetalPipelineShadersMSL21
pfMetalPipelineShadersMSL23
)
else()
list(APPEND plClient_SOURCES
main.cpp
Expand Down Expand Up @@ -158,17 +154,12 @@ if(APPLE)
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES"
XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER org.Huru.UruExplorer
XCODE_EMBED_RESOURCES "${plClient_SHADERTARGETS}"
)
target_compile_options(plClient PRIVATE -fobjc-arc)
target_sources(plClient PRIVATE Mac-Cocoa/Assets.xcassets)
set_source_files_properties(Mac-Cocoa/Assets.xcassets ${RESOURCES} PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)

if(${CMAKE_VERSION} VERSION_LESS 3.28)
message(FATAL_ERROR "Cannot build Mac client without CMake 3.28")
endif()

if(PLASMA_APPLE_DEVELOPMENT_TEAM_ID)
set_target_properties(plClient PROPERTIES
Expand All @@ -178,6 +169,13 @@ if(APPLE)
endif()
endif()

if(PLASMA_PIPELINE_METAL)
target_embed_metal_shader_libraries(plClient
pfMetalPipelineShadersMSL21
pfMetalPipelineShadersMSL23
)
endif()

if(PLASMA_BUILD_RESOURCE_DAT)
target_sources(plClient PRIVATE ${external_SCRIPTS} ${external_SOURCES} ${external_DAT})
endif()
Expand Down
72 changes: 31 additions & 41 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ set(pfMetalPipeline_HEADERS
pfMetalPipelineCreatable.h
)

set(pfMetalPipeline_SHADERS
ShaderSrc/FixedPipelineShaders.metal
ShaderSrc/PlateShaders.metal
ShaderSrc/BiasNormals.metal
ShaderSrc/CompCosines.metal
ShaderSrc/WaveSet7.metal
ShaderSrc/Grass.metal
ShaderSrc/WaveDecEnv.metal
ShaderSrc/Avatar.metal
ShaderSrc/WaveDec1Lay_7.metal
ShaderSrc/WaveRip.metal
ShaderSrc/Clear.metal
ShaderSrc/GammaCorrection.metal
ShaderSrc/TextFontShader.metal
)

plasma_library(pfMetalPipeline SOURCES ${pfMetalPipeline_SOURCES} ${pfMetalPipeline_HEADERS})
target_link_libraries(pfMetalPipeline
PUBLIC
Expand All @@ -70,47 +86,21 @@ source_group("Source Files" FILES ${pfMetalPipeline_SOURCES})
source_group("Header Files" FILES ${pfMetalPipeline_HEADERS})

# All supported Macs for Plasma/Metal support MSL 2.1
add_library(pfMetalPipelineShadersMSL21 MODULE)
# Build a 2.3 varient for macOS 11 and/or Apple Silicon specific features
add_library(pfMetalPipelineShadersMSL23 MODULE)

set(pfMetalPipeline_SHADERS
ShaderSrc/FixedPipelineShaders.metal
ShaderSrc/PlateShaders.metal
ShaderSrc/BiasNormals.metal
ShaderSrc/CompCosines.metal
ShaderSrc/WaveSet7.metal
ShaderSrc/Grass.metal
ShaderSrc/WaveDecEnv.metal
ShaderSrc/Avatar.metal
ShaderSrc/WaveDec1Lay_7.metal
ShaderSrc/WaveRip.metal
ShaderSrc/Clear.metal
ShaderSrc/GammaCorrection.metal
ShaderSrc/TextFontShader.metal
add_metal_shader_library(pfMetalPipelineShadersMSL21
STANDARD macos-metal2.1
${pfMetalPipeline_SHADERS}
)
set_target_properties(pfMetalPipelineShadersMSL21 PROPERTIES
XCODE_PRODUCT_TYPE com.apple.product-type.metal-library
XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal21
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/"
SUFFIX ".metallib"
PREFIX ""
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
)
set_target_properties(pfMetalPipelineShadersMSL23 PROPERTIES
XCODE_PRODUCT_TYPE com.apple.product-type.metal-library
XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal23
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/"
SUFFIX ".metallib"
PREFIX ""
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
target_include_directories(pfMetalPipelineShadersMSL21
PRIVATE
$<TARGET_PROPERTY:pnNucleusInc,INTERFACE_INCLUDE_DIRECTORIES>
)
set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL21 PROPERTIES LANGUAGE METAL)
set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL23 PROPERTIES LANGUAGE METAL)

target_sources(pfMetalPipelineShadersMSL21 PRIVATE ${pfMetalPipeline_SHADERS})
target_sources(pfMetalPipelineShadersMSL23 PRIVATE ${pfMetalPipeline_SHADERS})
# Build a 2.3 varient for macOS 11 and/or Apple Silicon specific features
add_metal_shader_library(pfMetalPipelineShadersMSL23
STANDARD macos-metal2.3
${pfMetalPipeline_SHADERS}
)
target_include_directories(pfMetalPipelineShadersMSL23
PRIVATE
$<TARGET_PROPERTY:pnNucleusInc,INTERFACE_INCLUDE_DIRECTORIES>
)
83 changes: 83 additions & 0 deletions cmake/CMakeDetermineMetalCompiler.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENCE.txt or https://cmake.org/licensing for details.

# CMakeDetermine(LANG)Compiler.cmake -> this should find the compiler for LANG and configure CMake(LANG)Compiler.cmake.in

include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)

if(NOT CMAKE_Metal_COMPILER_NAMES)
set(CMAKE_Metal_COMPILER_NAMES metal)
endif()

if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
set(CMAKE_Metal_COMPILER_XCODE_TYPE sourcecode.metal)

execute_process(COMMAND xcrun --find metal
OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _xcrun_err RESULT_VARIABLE _xcrun_result)
if(_xcrun_result EQUAL 0 AND EXISTS "${_xcrun_out}")
set(CMAKE_Metal_COMPILER "${_xcrun_out}")
else()
_cmake_find_compiler_path(Metal)
endif()
else()
if(CMAKE_Metal_COMPILER)
_cmake_find_compiler_path(Metal)
else()
set(CMAKE_Metal_COMPILER_INIT NOTFOUND)

if(NOT $ENV{METALC} STREQUAL "")
get_filename_component(CMAKE_Metal_COMPILER_INIT $ENV{METALC} PROGRAM PROGRAM_ARGS CMAKE_Metal_FLAGS_ENV_INIT)
if(CMAKE_Metal_FLAGS_ENV_INIT)
set(CMAKE_Metal_COMPILER_ARG1 "${CMAKE_Metal_FLAGS_ENV_INIT}" CACHE STRING "Arguments to the Metal compiler")
endif()
if(NOT EXISTS ${CMAKE_Metal_COMPILER_INIT})
message(FATAL_ERROR "Could not find compiler set in environment variable METALC\n$ENV{METALC}.\n${CMAKE_Metal_COMPILER_INIT}")
endif()
endif()

if(NOT CMAKE_Metal_COMPILER_INIT)
set(CMAKE_Metal_COMPILER_LIST metal ${_CMAKE_TOOLCHAIN_PREFIX}metal)
endif()

_cmake_find_compiler(Metal)
endif()

mark_as_advanced(CMAKE_Metal_COMPILER)
endif()

# For Metal we need to explicitly query the version.
if(CMAKE_Metal_COMPILER AND NOT CMAKE_Metal_COMPILER_VERSION)
execute_process(
COMMAND "${CMAKE_Metal_COMPILER}" --version
OUTPUT_VARIABLE output ERROR_VARIABLE output
RESULT_VARIABLE result
TIMEOUT 10
)
message(CONFIGURE_LOG
"Running the Metal compiler: \"${CMAKE_Metal_COMPILER}\" --version\n"
"${output}\n"
)

if(output MATCHES [[metal version ([0-9]+\.[0-9]+(\.[0-9]+)?)]])
set(CMAKE_Metal_COMPILER_VERSION "${CMAKE_MATCH_1}")
if(NOT CMAKE_Metal_COMPILER_ID)
set(CMAKE_Metal_COMPILER_ID "Apple")
endif()
endif()
endif()

if (NOT _CMAKE_TOOLCHAIN_LOCATION)
get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_Metal_COMPILER}" PATH)
endif ()

set(_CMAKE_PROCESSING_LANGUAGE "Metal")
include(CMakeFindBinUtils)
unset(_CMAKE_PROCESSING_LANGUAGE)

configure_file(
${CMAKE_CURRENT_LIST_DIR}/CMakeMetalCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake
)

set(CMAKE_Metal_COMPILER_ENV_VAR "METALC")
27 changes: 27 additions & 0 deletions cmake/CMakeMetalCompiler.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENCE.txt or https://cmake.org/licensing for details.

# CMake(LANG)Compiler.cmake.in -> used by CMakeDetermine(LANG)Compiler.cmake
# This file is used to store compiler information and is copied down into try
# compile directories so that try compiles do not need to re-determine and test
# the LANG

set(CMAKE_Metal_COMPILER "@CMAKE_Metal_COMPILER@")
set(CMAKE_Metal_COMPILER_ID "@CMAKE_Metal_COMPILER_ID@")
set(CMAKE_Metal_COMPILER_VERSION "@CMAKE_Metal_COMPILER_VERSION@")

set(CMAKE_Metal_COMPILER_LOADED 1)
set(CMAKE_Metal_COMPILER_WORKS "@CMAKE_Metal_COMPILER_WORKS@")

set(CMAKE_Metal_COMPILER_ENV_VAR "METALC")

set(CMAKE_Metal_COMPILER_ID_RUN "@CMAKE_Metal_COMPILER_ID_RUN@")
set(CMAKE_Metal_SOURCE_FILE_EXTENSIONS metal)
set(CMAKE_Metal_OUTPUT_EXTENSION ".air")
set(CMAKE_STATIC_LIBRARY_PREFIX_Metal "")
set(CMAKE_STATIC_LIBRARY_SUFFIX_Metal ".metal-ar")
set(CMAKE_SHARED_LIBRARY_PREFIX_Metal "")
set(CMAKE_SHARED_LIBRARY_SUFFIX_Metal ".metallib")
set(CMAKE_SHARED_MODULE_PREFIX_Metal "")
set(CMAKE_SHARED_MODULE_SUFFIX_Metal ".metallib")
set(CMAKE_EXECUTABLE_SUFFIX_Metal ".metallib")
78 changes: 78 additions & 0 deletions cmake/CMakeMetalInformation.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file LICENCE.txt or https://cmake.org/licensing for details.

# CMake(LANG)Information.cmake -> set up rule variables for LANG :
# CMAKE_(LANG)_CREATE_SHARED_LIBRARY
# CMAKE_(LANG)_CREATE_SHARED_MODULE
# CMAKE_(LANG)_CREATE_STATIC_LIBRARY
# CMAKE_(LANG)_COMPILE_OBJECT
# CMAKE_(LANG)_LINK_EXECUTABLE

include (CMakeCommonLanguageInclude)

set(CMAKE_Metal_FLAGS_INIT "-ffast-math")
set(CMAKE_Metal_FLAGS_DEBUG_INIT "-gline-tables-only -frecord-sources")
set(CMAKE_Metal_FLAGS_RELWITHDEBINFO_INIT "-gline-tables-only -frecord-sources")

cmake_initialize_per_config_variable(CMAKE_Metal_FLAGS "Flags used by the Metal compiler")

set(CMAKE_INCLUDE_FLAG_Metal "-I ")
set(CMAKE_Metal_COMPILER_ARG1 "")
set(CMAKE_Metal_DEFINE_FLAG -D)
set(CMAKE_Metal_FRAMEWORK_SEARCH_FLAG "-F ")
set(CMAKE_Metal_LIBRARY_PATH_FLAG "-L ")
set(CMAKE_Metal_SYSROOT_FLAG "-isysroot")
set(CMAKE_Metal_COMPILE_OPTIONS_TARGET "-target ")
set(CMAKE_DEPFILE_FLAGS_Metal "-MMD -MT dependencies -MF <DEP_FILE>")

if(CMAKE_GENERATOR MATCHES "Makefiles")
set(CMAKE_Metal_DEPFILE_FORMAT gcc)
set(CMAKE_Metal_DEPENDS_USE_COMPILER TRUE)
endif()

set(CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "${CMAKE_Metal_COMPILER}")
if(CMAKE_Metal_COMPILER_TARGET)
list(APPEND CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "-target" "${CMAKE_Metal_COMPILER_TARGET}")
endif()

# now define the following rule variables

# CMAKE_Metal_CREATE_SHARED_LIBRARY
# CMAKE_Metal_CREATE_SHARED_MODULE
# CMAKE_Metal_COMPILE_OBJECT
# CMAKE_Metal_LINK_EXECUTABLE

# variables supplied by the generator at use time
# <TARGET>
# <TARGET_BASE> the target without the suffix
# <OBJECTS>
# <OBJECT>
# <LINK_LIBRARIES>
# <FLAGS>
# <LINK_FLAGS>

# Metal compiler information
# <CMAKE_Metal_COMPILER>
# <CMAKE_SHARED_LIBRARY_CREATE_Metal_FLAGS>
# <CMAKE_SHARED_MODULE_CREATE_Metal_FLAGS>
# <CMAKE_Metal_LINK_FLAGS>

if(NOT CMAKE_Metal_COMPILE_OBJECT)
set(CMAKE_Metal_COMPILE_OBJECT
"<CMAKE_Metal_COMPILER> -c <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
endif()

if(NOT CMAKE_Metal_CREATE_SHARED_LIBRARY)
set(CMAKE_Metal_CREATE_SHARED_LIBRARY "<CMAKE_Metal_COMPILER> <CMAKE_SHARED_LIBRARY_Metal_FLAGS> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_Metal_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
endif()

if(NOT CMAKE_Metal_CREATE_SHARED_MODULE)
set(CMAKE_Metal_CREATE_SHARED_MODULE "${CMAKE_Metal_CREATE_SHARED_LIBRARY}")
endif()

if(NOT CMAKE_Metal_LINK_EXECUTABLE)
# Metal shaders don't really have "executables", but we need this for the try_compile to work properly, so we'll just have it output a metallib file
set(CMAKE_Metal_LINK_EXECUTABLE "<CMAKE_Metal_COMPILER> <FLAGS> <CMAKE_Metal_LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
endif()

set(CMAKE_Metal_INFORMATION_LOADED 1)
Loading

0 comments on commit 7ce9730

Please sign in to comment.