Skip to content
Open
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
101 changes: 101 additions & 0 deletions .github/workflows/testMacOS.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: testMacOS

on:
push:
branches:
- '**'
tags-ignore:
- 'v*'
pull_request:
branches:
- '**'

env:
BUILD_TYPE: Release
MACOSX_DEPLOYMENT_TARGET: "13.3"

jobs:
build:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
runs-on: macos-14

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install dependencies (Homebrew)
run: |
brew update
brew install cmake boost gtk+3 hdf5 libomp llvm make zlib

- name: Add Homebrew to PATH
run: echo "/opt/homebrew/bin" >> $GITHUB_PATH

- name: Add Homebrew LLVM to PATH
run: echo "/opt/homebrew/opt/llvm/bin" >> $GITHUB_PATH

- name: Set Xcode toolchain as default
run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

- name: Ensure system linker is used
run: echo "LD=/usr/bin/ld" >> $GITHUB_ENV

- name: Configure Homebrew clang (symlink for easier access)
run: |
brew unlink llvm && brew link llvm --force --overwrite

- name: Symlink system ld for Homebrew clang
run: |
ln -sf /usr/bin/ld /opt/homebrew/bin/ld
ln -sf /usr/bin/ld /opt/homebrew/opt/llvm/bin/ld

- name: Configure CMake with Homebrew clang and OpenMP support
env:
LDFLAGS: "-L/opt/homebrew/opt/libomp/lib -L/opt/homebrew/opt/zlib/lib"
CPPFLAGS: "-I/opt/homebrew/opt/libomp/include -I/opt/homebrew/opt/zlib/include"
PKG_CONFIG_PATH: "/opt/homebrew/opt/zlib/lib/pkgconfig:/opt/homebrew/lib/pkgconfig"
CC: "/opt/homebrew/opt/llvm/bin/clang"
CXX: "/opt/homebrew/opt/llvm/bin/clang++"
run: |
cmake -B build \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_MACOSX_RPATH=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET=${{env.MACOSX_DEPLOYMENT_TARGET}} \
-DCMAKE_INSTALL_RPATH="@loader_path;@rpath" \
-DCMAKE_PREFIX_PATH="/opt/homebrew/opt/hdf5;/opt/homebrew/opt/zlib;/opt/homebrew/opt/libomp" \
-DHDF5_ROOT=/opt/homebrew/opt/hdf5 \
-DZLIB_ROOT=/opt/homebrew/opt/zlib \
-DZLIB_INCLUDE_DIR=/opt/homebrew/opt/zlib/include \
-DZLIB_LIBRARY=/opt/homebrew/opt/zlib/lib/libz.dylib \
-DRAYX_WERROR=ON \
-DRAYX_REQUIRE_CUDA=OFF \
-DRAYX_ENABLE_CUDA=OFF \
-DRAYX_BUILD_RAYX_UI=OFF \
-DRAYX_BUILD_RAYX_CLI=ON \
-DRAYX_BUILD_RAYX_TESTS=ON \
-DCMAKE_C_COMPILER="$CC" \
-DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_CXX_FLAGS="-stdlib=libc++ -Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include -I/opt/homebrew/opt/zlib/include" \
-DCMAKE_EXE_LINKER_FLAGS="-L/opt/homebrew/opt/libomp/lib -L/opt/homebrew/opt/zlib/lib -lomp -lz"

- name: Build
run: |
cmake --build build --config ${{env.BUILD_TYPE}}

- name: Run
working-directory: ${{github.workspace}}
run: |
./build/bin/release/rayx -x -c -m 1 -i Intern/rayx-core/tests/input/BoringImagePlane.rml
./build/bin/release/rayx -x -m 1 -i Intern/rayx-core/tests/input/BoringImagePlane.rml
git checkout -- Intern/rayx-core/tests/input/BoringImagePlane.csv

- name: Test
working-directory: ${{github.workspace}}/build/bin/release
run: ./rayx-core-tst -x

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: RAYX-macOS-${{env.BUILD_TYPE}}
path: ${{github.workspace}}/build/bin/release
66 changes: 66 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

if(APPLE)
set(CMAKE_MACOSX_RPATH ON)
if(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.3")
endif()
endif()

# ---- Project ----
project(RAYX VERSION 1.1.0)
if(MSVC)
Expand Down Expand Up @@ -29,6 +36,65 @@ option(RAYX_BUILD_RAYX_TESTS "This option builds the RAYX test suite." ON)
option(RAYX_STATIC_LIB "This option builds 'rayx-core' as a static library." OFF)
# ------------------

# ---- Specific macos compiler options and flags concerning OpenMP ----
if(APPLE)
# Detect installed package manager. MacPorts wins if both are present, since
# its layout (libs directly under /opt/local) does not overlap with Homebrew.
# CMAKE_SYSTEM_PROCESSOR is only populated after project(), so this lives below it.
if(EXISTS "/opt/local/bin/port")
set(MACOS_PKG_PREFIX "/opt/local")
set(MACOS_PKG_KIND "macports")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
set(MACOS_PKG_PREFIX "/opt/homebrew")
set(MACOS_PKG_KIND "homebrew")
else()
set(MACOS_PKG_PREFIX "/usr/local")
set(MACOS_PKG_KIND "homebrew")
endif()
message(STATUS "macOS package manager: ${MACOS_PKG_KIND} at ${MACOS_PKG_PREFIX}")
set(CMAKE_INSTALL_RPATH "@loader_path;@rpath;${MACOS_PKG_PREFIX}/lib")

# OpenMP: MacPorts ships libomp directly under /opt/local; Homebrew uses an
# opt/<formula> subdirectory.
if(MACOS_PKG_KIND STREQUAL "macports")
set(OpenMP_INCLUDE_DIR "${MACOS_PKG_PREFIX}/include/libomp")
set(OpenMP_LIBRARY "${MACOS_PKG_PREFIX}/lib/libomp.dylib")
else()
set(OpenMP_INCLUDE_DIR "${MACOS_PKG_PREFIX}/opt/libomp/include")
set(OpenMP_LIBRARY "${MACOS_PKG_PREFIX}/opt/libomp/lib/libomp.dylib")
endif()

# Common OpenMP settings
set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp -I${OpenMP_INCLUDE_DIR}")
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I${OpenMP_INCLUDE_DIR}")
set(OpenMP_C_LIB_NAMES "omp")
set(OpenMP_CXX_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY "${OpenMP_LIBRARY}")
set(OpenMP_omp_INCLUDE_DIRS "${OpenMP_INCLUDE_DIR}")

if(RAYX_ENABLE_OPENMP)
find_package(OpenMP REQUIRED)
if(OpenMP_CXX_FOUND)
message(STATUS "OpenMP found:")
message(STATUS " Include dirs: ${OpenMP_CXX_INCLUDE_DIRS}")
message(STATUS " Libraries: ${OpenMP_CXX_LIBRARIES}")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
include_directories(${OpenMP_omp_INCLUDE_DIRS})
link_libraries(${OpenMP_omp_LIBRARY})
endif()
endif()

# HDF5: MacPorts installs into /opt/local directly; Homebrew uses opt/hdf5.
if(MACOS_PKG_KIND STREQUAL "macports")
set(HDF5_ROOT "${MACOS_PKG_PREFIX}")
else()
set(HDF5_ROOT "${MACOS_PKG_PREFIX}/opt/hdf5")
endif()
find_package(HDF5 REQUIRED COMPONENTS C HL)

endif()


# ---- Build options ----
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/release)
Expand Down
6 changes: 5 additions & 1 deletion Intern/rayx-core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

# ---- Install directories ----
include(GNUInstallDirs)
set(INSTALL_DATA_DIR ${CMAKE_INSTALL_DATADIR})

# ---- for files compiled with cuda compiler, prepend -Xcompiler flags ----
function(prepend_xcompiler FLAG_LIST PREPENDED_FLAG_LIST)
set(SRC ${${FLAG_LIST}})
Expand Down Expand Up @@ -144,7 +148,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(COMPILE_PLATFORM RAYX_PLATFORM_GCC)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILE_PLATFORM RAYX_PLATFORM_MSVC)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(COMPILE_PLATFORM RAYX_PLATFORM_CLANG)
else()
message(STATUS "Use undefined compiler: ${CMAKE_CXX_COMPILER_ID}")
Expand Down
6 changes: 6 additions & 0 deletions Intern/rayx-core/src/Debug/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,14 @@ inline std::vector<double> formatAsVec(T) {
}

inline std::vector<double> formatAsVec(int arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(long arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(RandCounter arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(EventType arg) { return {static_cast<double>(arg)}; }
// Catch remaining integral types (e.g. size_t) not already covered above.
// size_t == unsigned long on Linux (same as RandCounter) but differs on macOS arm64.
template <typename T>
requires(std::is_integral_v<T> && !std::is_same_v<T, int> && !std::is_same_v<T, RandCounter>)
inline std::vector<double> formatAsVec(T arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(double arg) { return {arg}; }
inline std::vector<double> formatAsVec(complex::Complex arg) { return {arg.real(), arg.imag()}; }

Expand Down
18 changes: 14 additions & 4 deletions Intern/rayx-core/src/Rml/Locate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#if defined(_WIN32)
#include <windows.h>
#elif defined(__APPLE__)
#include <cassert>
#include <climits>
#include <mach-o/dyld.h>
#else
#include <limits.h>
#include <unistd.h>
Expand Down Expand Up @@ -63,8 +64,13 @@ std::filesystem::path ResourceHandler::getExecutablePath() {
buffer.resize(buffer.size() * 2);
}

#else
static_assert(false, "macOS support is not implemented yet");
#elif defined(__APPLE__)
std::vector<char> buffer(PATH_MAX);
uint32_t size = buffer.size();
if (_NSGetExecutablePath(buffer.data(), &size) != 0) {
buffer.resize(size);
_NSGetExecutablePath(buffer.data(), &size);
}
#endif
return std::filesystem::path(buffer.data());
}
Expand Down Expand Up @@ -112,7 +118,11 @@ std::filesystem::path ResourceHandler::getFullPath(const std::filesystem::path&
if (fileExists(path)) return found(path);

#elif defined(__APPLE__)
static_assert(false, "macOS support is not implemented yet");
// Look next to the executable
std::filesystem::path execDir = getExecutablePath().parent_path();
std::filesystem::path path = execDir / relativePath;
RAYX_VERB << "\tlooking at " << path;
if (fileExists(path)) return found(path);

#endif
// Not found -> empty path
Expand Down
Loading
Loading