Adds a macOS post-build step to patch CEF’s keychain service string to a Nebula-specific name, then re-sign the modified framework (with configurable signing identity or ad-hoc). Also enables Chromium’s `use-mock-keychain` switch on Apple builds to prevent repeated local keychain prompts, fixes titlebar traffic-light hit testing in the mac window view, scopes a WM_CLOSE guard to Windows only, and updates `.clangd` to ignore non-mac platform sources during macOS development.
347 lines
13 KiB
CMake
347 lines
13 KiB
CMake
cmake_minimum_required(VERSION 3.21)
|
|
|
|
# Enable OBJCXX early on macOS for Cocoa integration
|
|
if(APPLE)
|
|
project(NebulaBrowser LANGUAGES CXX OBJCXX)
|
|
else()
|
|
project(NebulaBrowser LANGUAGES CXX)
|
|
endif()
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
# ------------------------------------------------------------
|
|
# CEF location
|
|
# ------------------------------------------------------------
|
|
|
|
set(CEF_ROOT "${CMAKE_SOURCE_DIR}/thirdparty/cef" CACHE PATH "Path to the CEF binary distribution")
|
|
|
|
if(NOT EXISTS "${CEF_ROOT}/cmake/FindCEF.cmake")
|
|
message(FATAL_ERROR
|
|
"CEF was not found.\n"
|
|
"Expected CEF here:\n"
|
|
" ${CEF_ROOT}\n\n"
|
|
"Unpack the CEF binary distribution for your OS into thirdparty/cef."
|
|
)
|
|
endif()
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CEF_ROOT}/cmake")
|
|
find_package(CEF REQUIRED)
|
|
|
|
add_subdirectory(
|
|
"${CEF_LIBCEF_DLL_WRAPPER_PATH}"
|
|
"${CMAKE_BINARY_DIR}/libcef_dll_wrapper"
|
|
)
|
|
|
|
SET_CEF_TARGET_OUT_DIR()
|
|
|
|
# ------------------------------------------------------------
|
|
# Sources
|
|
# ------------------------------------------------------------
|
|
|
|
set(NEBULA_COMMON_SOURCES
|
|
src/app/first_run_state.cpp
|
|
src/app/nebula_controller.cpp
|
|
src/app/run.cpp
|
|
src/browser/session_state.cpp
|
|
src/browser/tab.cpp
|
|
src/browser/tab_manager.cpp
|
|
src/browser/url_utils.cpp
|
|
src/cef/browser_client.cpp
|
|
src/cef/nebula_app.cpp
|
|
src/extensions/extension_manager.cpp
|
|
src/ui/paths.cpp
|
|
)
|
|
|
|
if(OS_WINDOWS)
|
|
set(NEBULA_PLATFORM_SOURCES
|
|
src/platform/win/default_browser_win.cpp
|
|
src/platform/win/paths_win.cpp
|
|
src/platform/win/process_win.cpp
|
|
src/platform/win/startup_win.cpp
|
|
src/platform/win/browser_host_win.cpp
|
|
src/platform/win/nebula_window_win.cpp
|
|
resources/nebula.rc
|
|
)
|
|
elseif(OS_MACOSX)
|
|
set(NEBULA_PLATFORM_SOURCES
|
|
src/platform/mac/default_browser_mac.mm
|
|
src/platform/mac/paths_mac.cpp
|
|
src/platform/mac/process_mac.cpp
|
|
src/platform/mac/startup_mac.mm
|
|
src/platform/mac/browser_host_mac.mm
|
|
src/platform/mac/nebula_window_mac.mm
|
|
)
|
|
set_source_files_properties(
|
|
src/platform/mac/startup_mac.mm
|
|
src/platform/mac/browser_host_mac.mm
|
|
src/platform/mac/nebula_window_mac.mm
|
|
PROPERTIES
|
|
COMPILE_FLAGS "-fobjc-arc"
|
|
)
|
|
elseif(OS_LINUX)
|
|
set(NEBULA_PLATFORM_SOURCES
|
|
src/platform/linux/default_browser_linux.cpp
|
|
src/platform/linux/paths_linux.cpp
|
|
src/platform/linux/process_linux.cpp
|
|
src/platform/linux/startup_linux.cpp
|
|
src/platform/linux/browser_host_linux.cpp
|
|
src/platform/linux/nebula_window_linux.cpp
|
|
)
|
|
else()
|
|
message(FATAL_ERROR "Unsupported platform.")
|
|
endif()
|
|
|
|
# On macOS, CEF is a framework linked via CEF_STANDARD_LIBS.
|
|
# On Windows/Linux, we create a logical target for libcef.
|
|
if(NOT OS_MACOSX)
|
|
ADD_LOGICAL_TARGET("libcef_lib" "${CEF_LIB_RELEASE}" "${CEF_LIB_DEBUG}")
|
|
endif()
|
|
|
|
if(OS_LINUX)
|
|
FIND_LINUX_LIBRARIES("X11")
|
|
endif()
|
|
|
|
# Compile Icon Composer .icon into Assets.car + .icns for macOS app bundles.
|
|
if(OS_MACOSX)
|
|
set(NEBULA_MAC_ICON_SOURCE "${CMAKE_SOURCE_DIR}/assets/images/branding/MacOSIcon.icon")
|
|
set(NEBULA_MAC_ICON_OUTDIR "${CMAKE_BINARY_DIR}/generated/MacOSIcon")
|
|
set(NEBULA_MAC_ICON_ICNS "${NEBULA_MAC_ICON_OUTDIR}/MacOSIcon.icns")
|
|
set(NEBULA_MAC_ICON_CAR "${NEBULA_MAC_ICON_OUTDIR}/Assets.car")
|
|
set(NEBULA_MAC_ICON_PARTIAL "${NEBULA_MAC_ICON_OUTDIR}/partial.plist")
|
|
|
|
add_custom_command(
|
|
OUTPUT "${NEBULA_MAC_ICON_ICNS}" "${NEBULA_MAC_ICON_CAR}"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${NEBULA_MAC_ICON_OUTDIR}"
|
|
COMMAND xcrun actool
|
|
"${NEBULA_MAC_ICON_SOURCE}"
|
|
--compile "${NEBULA_MAC_ICON_OUTDIR}"
|
|
--platform macosx
|
|
--minimum-deployment-target "${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
|
--app-icon MacOSIcon
|
|
--output-partial-info-plist "${NEBULA_MAC_ICON_PARTIAL}"
|
|
DEPENDS
|
|
"${NEBULA_MAC_ICON_SOURCE}/icon.json"
|
|
"${NEBULA_MAC_ICON_SOURCE}/Assets/Nebula-Favicon.png"
|
|
COMMENT "Compiling MacOSIcon.icon for app bundle"
|
|
VERBATIM
|
|
)
|
|
add_custom_target(NebulaMacAppIcon DEPENDS
|
|
"${NEBULA_MAC_ICON_ICNS}"
|
|
"${NEBULA_MAC_ICON_CAR}"
|
|
)
|
|
endif()
|
|
|
|
function(add_nebula_app_target nebula_target entry_source)
|
|
if(OS_WINDOWS)
|
|
add_executable(${nebula_target} WIN32
|
|
${entry_source}
|
|
${NEBULA_COMMON_SOURCES}
|
|
${NEBULA_PLATFORM_SOURCES}
|
|
)
|
|
elseif(OS_MACOSX)
|
|
add_executable(${nebula_target} MACOSX_BUNDLE
|
|
${entry_source}
|
|
${NEBULA_COMMON_SOURCES}
|
|
${NEBULA_PLATFORM_SOURCES}
|
|
)
|
|
elseif(OS_LINUX)
|
|
add_executable(${nebula_target}
|
|
${entry_source}
|
|
${NEBULA_COMMON_SOURCES}
|
|
${NEBULA_PLATFORM_SOURCES}
|
|
)
|
|
endif()
|
|
|
|
SET_EXECUTABLE_TARGET_PROPERTIES(${nebula_target})
|
|
add_dependencies(${nebula_target} libcef_dll_wrapper)
|
|
|
|
target_include_directories(${nebula_target} PRIVATE
|
|
"${CMAKE_SOURCE_DIR}/src"
|
|
"${CEF_ROOT}"
|
|
"${CEF_ROOT}/include"
|
|
)
|
|
|
|
if(OS_MACOSX)
|
|
# On macOS, CEF is a framework; don't link libcef_lib
|
|
target_link_libraries(${nebula_target} PRIVATE
|
|
libcef_dll_wrapper
|
|
${CEF_STANDARD_LIBS}
|
|
)
|
|
else()
|
|
target_link_libraries(${nebula_target} PRIVATE
|
|
libcef_lib
|
|
libcef_dll_wrapper
|
|
${CEF_STANDARD_LIBS}
|
|
)
|
|
endif()
|
|
|
|
if(MSVC)
|
|
set_property(TARGET ${nebula_target} PROPERTY
|
|
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
|
|
)
|
|
endif()
|
|
|
|
# ------------------------------------------------------------
|
|
# Platform-specific CEF runtime deployment
|
|
# ------------------------------------------------------------
|
|
|
|
if(OS_WINDOWS)
|
|
target_link_libraries(${nebula_target} PRIVATE dwmapi)
|
|
target_include_directories(${nebula_target} PRIVATE
|
|
"${CMAKE_SOURCE_DIR}/resources"
|
|
)
|
|
target_compile_definitions(${nebula_target} PRIVATE
|
|
NOMINMAX
|
|
WIN32_LEAN_AND_MEAN
|
|
)
|
|
COPY_FILES("${nebula_target}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR_RELEASE}" "${CEF_TARGET_OUT_DIR}")
|
|
COPY_FILES("${nebula_target}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
|
elseif(OS_LINUX)
|
|
COPY_FILES("${nebula_target}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR_RELEASE}" "${CEF_TARGET_OUT_DIR}")
|
|
COPY_FILES("${nebula_target}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
|
elseif(OS_MACOSX)
|
|
target_link_libraries(${nebula_target} PRIVATE
|
|
"-framework Cocoa"
|
|
"-framework ApplicationServices"
|
|
)
|
|
set(NEBULA_APP "${CEF_TARGET_OUT_DIR}/${nebula_target}.app")
|
|
set(NEBULA_HELPER_TARGET "${nebula_target}_Helper")
|
|
set(NEBULA_HELPER_OUTPUT_NAME "${nebula_target} Helper")
|
|
string(TOLOWER "${nebula_target}" NEBULA_HELPER_BUNDLE_NAME)
|
|
|
|
set_target_properties(${nebula_target} PROPERTIES
|
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/cmake/mac-Info.plist.in"
|
|
MACOSX_BUNDLE_BUNDLE_NAME "${nebula_target}"
|
|
MACOSX_BUNDLE_GUI_IDENTIFIER "com.nebula.browser.${nebula_target}"
|
|
MACOSX_BUNDLE_BUNDLE_VERSION "1.0"
|
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0"
|
|
MACOSX_BUNDLE_LONG_VERSION_STRING "1.0"
|
|
MACOSX_BUNDLE_COPYRIGHT "Nebula Browser"
|
|
)
|
|
add_dependencies(${nebula_target} NebulaMacAppIcon)
|
|
add_custom_command(TARGET ${nebula_target} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
|
"${NEBULA_APP}/Contents/Resources"
|
|
COMMAND ${CMAKE_COMMAND} -E copy
|
|
"${NEBULA_MAC_ICON_ICNS}"
|
|
"${NEBULA_APP}/Contents/Resources/MacOSIcon.icns"
|
|
COMMAND ${CMAKE_COMMAND} -E copy
|
|
"${NEBULA_MAC_ICON_CAR}"
|
|
"${NEBULA_APP}/Contents/Resources/Assets.car"
|
|
COMMENT "Installing MacOSIcon into ${nebula_target}.app"
|
|
VERBATIM
|
|
)
|
|
|
|
COPY_MAC_FRAMEWORK(
|
|
"${nebula_target}"
|
|
"${CEF_BINARY_DIR_RELEASE}"
|
|
"${NEBULA_APP}"
|
|
)
|
|
COPY_FILES(
|
|
"${nebula_target}"
|
|
"${CEF_BINARY_FILES}"
|
|
"${CEF_BINARY_DIR_RELEASE}"
|
|
"${NEBULA_APP}/Contents/Frameworks"
|
|
)
|
|
COPY_FILES(
|
|
"${nebula_target}"
|
|
"${CEF_RESOURCE_FILES}"
|
|
"${CEF_RESOURCE_DIR}"
|
|
"${NEBULA_APP}/Contents/Resources"
|
|
)
|
|
|
|
foreach(_suffix_list ${CEF_HELPER_APP_SUFFIXES})
|
|
string(REPLACE ":" ";" _suffix_list ${_suffix_list})
|
|
list(GET _suffix_list 0 _name_suffix)
|
|
list(GET _suffix_list 1 _target_suffix)
|
|
list(GET _suffix_list 2 _plist_suffix)
|
|
|
|
set(_helper_target "${NEBULA_HELPER_TARGET}${_target_suffix}")
|
|
set(_helper_output_name "${NEBULA_HELPER_OUTPUT_NAME}${_name_suffix}")
|
|
set(_helper_info_plist "${CMAKE_CURRENT_BINARY_DIR}/${_helper_target}-Info.plist")
|
|
|
|
file(READ "${CMAKE_SOURCE_DIR}/cmake/mac-helper-Info.plist.in" _plist_contents)
|
|
string(REPLACE "\${EXECUTABLE_NAME}" "${_helper_output_name}" _plist_contents "${_plist_contents}")
|
|
string(REPLACE "\${PRODUCT_NAME}" "${_helper_output_name}" _plist_contents "${_plist_contents}")
|
|
string(REPLACE "\${HELPER_BUNDLE_NAME}" "${NEBULA_HELPER_BUNDLE_NAME}" _plist_contents "${_plist_contents}")
|
|
string(REPLACE "\${BUNDLE_ID_SUFFIX}" "${_plist_suffix}" _plist_contents "${_plist_contents}")
|
|
file(WRITE "${_helper_info_plist}" "${_plist_contents}")
|
|
|
|
add_executable(${_helper_target} MACOSX_BUNDLE
|
|
app/process_helper_mac.cc
|
|
src/cef/nebula_app.cpp
|
|
)
|
|
SET_EXECUTABLE_TARGET_PROPERTIES(${_helper_target})
|
|
add_dependencies(${_helper_target} libcef_dll_wrapper)
|
|
target_include_directories(${_helper_target} PRIVATE
|
|
"${CMAKE_SOURCE_DIR}/src"
|
|
"${CEF_ROOT}"
|
|
"${CEF_ROOT}/include"
|
|
)
|
|
target_link_libraries(${_helper_target} PRIVATE
|
|
libcef_dll_wrapper
|
|
${CEF_STANDARD_LIBS}
|
|
)
|
|
set_target_properties(${_helper_target} PROPERTIES
|
|
MACOSX_BUNDLE_INFO_PLIST "${_helper_info_plist}"
|
|
OUTPUT_NAME "${_helper_output_name}"
|
|
)
|
|
|
|
add_dependencies(${nebula_target} "${_helper_target}")
|
|
add_custom_command(TARGET ${nebula_target} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${CEF_TARGET_OUT_DIR}/${_helper_output_name}.app"
|
|
"${NEBULA_APP}/Contents/Frameworks/${_helper_output_name}.app"
|
|
VERBATIM
|
|
)
|
|
endforeach()
|
|
|
|
# Give Nebula its own OSCrypt keychain service name, then resign so the
|
|
# patched framework still loads. Optional stable identity:
|
|
# cmake -DNEBULA_CODESIGN_IDENTITY="Apple Development: ..."
|
|
set(NEBULA_CODESIGN_IDENTITY "" CACHE STRING
|
|
"codesign identity for macOS app bundles (empty = ad-hoc)")
|
|
if(NEBULA_CODESIGN_IDENTITY)
|
|
set(_nebula_codesign_identity "${NEBULA_CODESIGN_IDENTITY}")
|
|
else()
|
|
set(_nebula_codesign_identity "-")
|
|
endif()
|
|
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
|
set(_nebula_cef_framework
|
|
"${NEBULA_APP}/Contents/Frameworks/Chromium Embedded Framework.framework")
|
|
set(_nebula_cef_binary
|
|
"${_nebula_cef_framework}/Versions/Current/Chromium Embedded Framework")
|
|
add_custom_command(TARGET ${nebula_target} POST_BUILD
|
|
COMMAND ${Python3_EXECUTABLE}
|
|
"${CMAKE_SOURCE_DIR}/cmake/macos_patch_cef_keychain.py"
|
|
"${_nebula_cef_binary}"
|
|
COMMAND codesign --force --sign "${_nebula_codesign_identity}" --timestamp=none
|
|
"${_nebula_cef_binary}"
|
|
COMMAND codesign --force --sign "${_nebula_codesign_identity}" --timestamp=none
|
|
"${_nebula_cef_framework}"
|
|
COMMENT "Patching CEF keychain service name and resigning framework"
|
|
VERBATIM
|
|
)
|
|
endif()
|
|
|
|
# ------------------------------------------------------------
|
|
# Copy Nebula UI files after build
|
|
# ------------------------------------------------------------
|
|
|
|
add_custom_command(TARGET ${nebula_target} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${CMAKE_SOURCE_DIR}/ui"
|
|
"$<TARGET_FILE_DIR:${nebula_target}>/ui"
|
|
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${CMAKE_SOURCE_DIR}/assets"
|
|
"$<TARGET_FILE_DIR:${nebula_target}>/ui/assets"
|
|
|
|
COMMENT "Copying Nebula UI files and assets for ${nebula_target}..."
|
|
)
|
|
endfunction()
|
|
|
|
add_nebula_app_target(NebulaBrowser app/main.cpp)
|
|
add_nebula_app_target(NebulaBigPicture app/main_bigpicture.cpp)
|