Skip to content

Commit

Permalink
Codesigning vapor on Apple Silicon (#3639)
Browse files Browse the repository at this point in the history
* resource path working

* resource path working on local builds

* cleanup and linux test

* cleanup

* build test

* build test

* build test

* build test

* build test

* build test

* macos test

* codesigning validated

* test

* final test 1

* final test 3

* final test 4

* final test 5

* final test 6

* final test 7

* final test 8

* final test 9

* final commit

* turn ospray off
  • Loading branch information
sgpearse authored Jul 29, 2024
1 parent afabe9f commit fbb9195
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 231 deletions.
246 changes: 73 additions & 173 deletions .circleci/config.yml

Large diffs are not rendered by default.

64 changes: 44 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ else()

list (APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_LIB_DIR})
list (APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_DIR})
list (APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_DIR}/HDF_Group/HDF5/1.12.2/lib)
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
list (APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_DIR}/h5/lib)
else()
list (APPEND CMAKE_PREFIX_PATH ${THIRD_PARTY_DIR}/HDF_Group/HDF5/1.12.2/lib)
endif()

if (APPLE)
set(CMAKE_MODULE_PATH /opt/local/lib/libomp)
Expand Down Expand Up @@ -210,23 +214,33 @@ message("Library EXPAT = ${EXPAT}")
function(FIND_BUNDLED_PYTHON)
# FindPython supports Python_ROOT_DIR however vapor's bundled python distribution
# does not conform to its requirements so this manually configures the results
message("Using bundled python")
message("Using bundled python ${PYTHONDIR} ${PYTHONPATH}")
set(Python_VERSION "${PYTHONVERSION}")
set(Python_NumPy_INCLUDE_DIRS "${NUMPY_INCLUDE_DIR}")
unset(Python_LIBRARIES) # This is required for find_library to work in certain cases
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
set(PYTHON_LIB_DIR "${PYTHONDIR}/lib")
else()
set(PYTHON_LIB_DIR "${PYTHONPATH}")
endif()
find_library(
Python_LIBRARIES
NAMES python${PYTHONVERSION} python${PYTHONVERSION}m
PATHS ${THIRD_PARTY_LIB_DIR} ${PYTHONPATH}
NAMES python${PYTHONVERSION} python${PYTHONVERSION}m
PATHS ${THIRD_PARTY_LIB_DIR} ${PYTHON_LIB_DIR}
NO_DEFAULT_PATH
)

if (WIN32)
set(Python_SITELIB "${PYTHONPATH}/Lib/site-packages")
set(Python_INCLUDE_DIRS "${THIRD_PARTY_DIR}/Python${PYTHONVERSION}/include")
else()
set(Python_SITELIB "${PYTHONPATH}/site-packages")
if (NOT DEFINED Python_INCLUDE_DIRS)
set(Python_INCLUDE_DIRS "${THIRD_PARTY_INC_DIR}/python${PYTHONVERSION}")
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
set(Python_INCLUDE_DIRS "${PYTHONDIR}/include/python${PYTHONVERSION}")
else()
set(Python_INCLUDE_DIRS "${THIRD_PARTY_INC_DIR}/python${PYTHONVERSION}")
endif()
endif()
endif()

Expand Down Expand Up @@ -301,9 +315,12 @@ elseif (APPLE)
set (CMAKE_INSTALL_PREFIX /Applications)
set (INSTALL_BIN_DIR ./vapor.app/Contents/MacOS)
set (INSTALL_SHARE_DIR ./vapor.app/Contents/share)
#set (INSTALL_LIB_DIR ./vapor.app/Contents/lib)
set (INSTALL_LIB_DIR ./vapor.app/Contents/Frameworks)
set (INSTALL_INCLUDE_DIR ./vapor.app/Contents/include/vapor)
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
set (INSTALL_LIB_DIR ./vapor.app/Contents/Frameworks)
else ()
set (INSTALL_LIB_DIR ./vapor.app/Contents/lib)
endif()
else ()
set (INSTALL_BIN_DIR bin)
set (INSTALL_LIB_DIR lib)
Expand All @@ -312,10 +329,11 @@ elseif (APPLE)
endif ()

if (BUILD_PYTHON)
set (CMAKE_INSTALL_RPATH "@loader_path")
else ()
#set (CMAKE_INSTALL_RPATH "@executable_path/../lib")
set (CMAKE_INSTALL_RPATH "@executable_path/../Frameworks")
set (CMAKE_INSTALL_RPATH "@loader_path")
elseif ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
set (CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/../Resources")
else()
set (CMAKE_INSTALL_RPATH "@executable_path/../lib")
endif ()

if (DIST_INSTALLER AND USE_OMP)
Expand Down Expand Up @@ -428,18 +446,11 @@ if (APPLE)
set (CPACK_BINARY_DRAGNDROP ON)
if (DIST_INSTALLER AND GENERATE_FULL_INSTALLER)
file (GLOB INSTALL_LIBS ${THIRD_PARTY_LIB_DIR}/*.dylib)
#file (GLOB INSTALL_FRAMEWORKS ${THIRD_PARTY_LIB_DIR}/*.framework)
file (GLOB INSTALL_GUI_FRAMEWORKS ${PYTHONPATH})
install (
FILES ${INSTALL_LIBS}
DESTINATION ${INSTALL_LIB_DIR}
COMPONENT Dependencies
)
#install (
# DIRECTORY ${INSTALL_FRAMEWORKS}
# DESTINATION ${INSTALL_LIB_DIR}
# COMPONENT Dependencies
# )

set (FRAMEWORKS Core OpenGL Widgets Gui DBus Network PrintSupport)
foreach(item IN LISTS FRAMEWORKS)
Expand All @@ -463,9 +474,22 @@ if (APPLE)
endif ()

if (NOT BUILD_PYTHON)
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
file (GLOB INSTALL_GUI_FRAMEWORKS ${PYTHONDIR})
set (PYTHON_DESTINATION "${INSTALL_LIB_DIR}/../Resources")
else()
file (GLOB INSTALL_GUI_FRAMEWORKS ${PYTHONPATH})
set (PYTHON_DESTINATION "${INSTALL_LIB_DIR}")
endif()
install (
DIRECTORY ${INSTALL_GUI_FRAMEWORKS}
DESTINATION ${INSTALL_LIB_DIR}
DIRECTORY ${INSTALL_GUI_FRAMEWORKS}
DESTINATION ${PYTHON_DESTINATION}
COMPONENT Dependencies
PATTERN "bin" EXCLUDE
)
install (
FILES ${Python_LIBRARIES}
DESTINATION ${PYTHON_DESTINATION}
COMPONENT Dependencies
)
file (GLOB COCOA_LIBS ${THIRD_PARTY_DIR}/plugins/platforms/libqcocoa.dylib)
Expand Down
61 changes: 61 additions & 0 deletions buildutils/codesignMacOS.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
set +e

installDir="/Applications"
dmgName="VAPOR3-3.9.3-AppleSilicon.dmg"
dmgDir="tmp"

#for file in ${installDir}/vapor.app/Contents/Frameworks/*; do
# codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --timestamp --verbose $file
#done

# Deploy Qt with macdeployqt
# N.B. Apple's notorization will give an "bundle format is ambiguous (could be app or framework)" if Qt's frameworks are missing symlinks
# So, if copying the third party libraries use 'cp -a /old/libs /new/libs' and not 'cp -r /old/libs /new/libs' (-a and not -r)
/usr/local/VAPOR-Deps/current/bin/macdeployqt ${installDir}/vapor.app -timestamp -sign-for-notarization="Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)"

# Codesign libraries and frameworks
find ${installDir}/vapor.app/Contents/Frameworks -type f -exec file {} + | grep -E 'Mach-O .* shared library' | cut -d: -f1 | while read -r file; do
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --timestamp --force --deep --verbose --options runtime "$file"
done

# Codesign plugins and python
directories=(
"${installDir}/vapor.app/Contents/share/plugins/"
"${installDir}/vapor.app/Contents/Resources/"
"${installDir}/vapor.app/Contents/Resources/python/lib/"
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/numpy/.dylibs"
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/PIL/.dylibs"
"${installDir}/vapor.app/Contents/Resources/python/lib/python3.9/site-packages/scipy/.dylibs"
)
for dir in "${directories[@]}"; do
find "$dir" -type f \( -name "*.so" -o -name "*.dylib" \) | while read -r file; do
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --timestamp --force --deep --verbose $file
done
done

# Codesign additional MacOS plugins
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --verbose ${installDir}/vapor.app/Contents/MacOS/platforms/libqcocoa.dylib
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --verbose ${installDir}/vapor.app/Contents/MacOS/styles/libqmacstyle.dylib

# Codesign all vapor executables with timestamp and hardended runtime
for file in ${installDir}/vapor.app/Contents/MacOS/*; do
codesign --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" --force --deep --timestamp --verbose --options runtime $file
done

# Create .dmg that contains symlink to /Applications
mkdir -p "${dmgDir}"
cp -R "${installDir}/vapor.app" "${dmgDir}"
ln -s /Applications "${dmgDir}/Applications"
hdiutil create -volname "vapor" -srcfolder ${dmgDir} -ov -format UDZO "${installDir}/${dmgName}"
rm -rf "${dmgDir}"

# Sign and notarize the .dmg
codesign --force --verify --verbose --sign "Developer ID Application: University Corporation for Atmospheric Research (DQ4ZFL4KLF)" ${installDir}/${dmgName}
xcrun -v notarytool submit ${installDir}/${dmgName} --keychain-profile "testApp-password" --wait

# Staple the notarized .dmg
xcrun stapler staple ${installDir}/${dmgName}
xcrun stapler validate ${installDir}/${dmgName}

# Fetch the notorization log
# xcrun notarytool log --keychain-profile "testApp-password" <hash>
4 changes: 4 additions & 0 deletions lib/common/GetAppPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ std::string Wasp::GetAppPath(const string &app, const string &resource, const ve
path.append("share");
} else if (myResource.compare("lib") == 0) {
path.append("lib");
} else if (myResource.compare("Frameworks") == 0) {
path.append("Frameworks");
} else if (myResource.compare("Resources") == 0) {
path.append("Resources");
} else if (myResource.compare("home") == 0) {
path.erase(path.size() - 1, 1);
} else { // must be plugins
Expand Down
20 changes: 13 additions & 7 deletions lib/common/ResourcePath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ std::string Wasp::GetResourcePath(const std::string &name)

std::string Wasp::GetSharePath(const std::string &name) { return GetResourcePath("share/" + name); }

#ifdef WIN32
#if defined(WIN32)
#define PYTHON_INSTALLED_PATH ("python" + string(PYTHON_VERSION))
#elif defined(__aarch64__)
#define PYTHON_INSTALLED_PATH ("Resources/python")
#else
#define PYTHON_INSTALLED_PATH ("lib/python" + string(PYTHON_VERSION))
#endif
Expand All @@ -119,12 +121,16 @@ std::string Wasp::GetPythonDir()
#ifdef WIN32
return GetPythonPath();
#endif

string path = GetResourcePath("");

string exists = FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH});

if (!FileUtils::Exists(FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH}))) path = string(PYTHON_DIR);
string path = string(PYTHON_DIR); // Try our third-party-library directory first
if (!FileUtils::Exists(path)) {
path = GetResourcePath("");
string exists = FileUtils::JoinPaths({path, PYTHON_INSTALLED_PATH});
if (!exists.empty()) {
#if defined(__aarch64__)
path = exists; // If the third-party-library directory doesn't exist, use the python installed path. Otherwise, use the root.
#endif
}
}
return path;
}

Expand Down
12 changes: 12 additions & 0 deletions lib/render/OSPRay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ using namespace VOSP;
#ifdef BUILD_OSPRAY
static int _initialized = false;

#if defined(__aarch64__)
void ospErrorCallback(void* userData, OSPError error, const char *msg)
#else
void ospErrorCallback(OSPError error, const char *msg)
#endif
{
fprintf(stderr, "OSP error ");
switch (error) {
Expand Down Expand Up @@ -44,7 +48,11 @@ int VOSP::Initialize(int *argc, char **argv)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
// If this is not set, OSPRay will crash upon shutdown
#if defined(__aarch64__)
ospDeviceSetErrorCallback(ospGetCurrentDevice(), ospErrorCallback, nullptr);
#else
ospDeviceSetErrorFunc(ospGetCurrentDevice(), ospErrorCallback);
#endif
#pragma GCC diagnostic pop
_initialized = true;
return 0;
Expand Down Expand Up @@ -184,7 +192,11 @@ OSPGeometricModel Test::LoadTriangle(glm::vec3 scale, const std::string &rendere

ospCommit(mesh);

#if defined(__aarch64__)
OSPMaterial mat = ospNewMaterial(rendererType.c_str());
#else
OSPMaterial mat = ospNewMaterial(rendererType.c_str(), "obj");
#endif
ospCommit(mat);

// put the mesh into a model
Expand Down
57 changes: 28 additions & 29 deletions scripts/build3rdParty.sh
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ pythonVapor() {
#LDFLAGS="-L$installDir/lib -L$(brew --prefix zlib)/lib -I$(brew --prefix openssl)/lib" \
#CPPFLAGS="-I$installDir/include -I$(brew --prefix zlib)/include -I$(brew --prefix openssl)/include" \
if [ "$OS" = "macOSx86" ] || [ "$OS" = "M1" ]; then
args+=(--libdir=$installDir/Resources)
args+=(--with-openssl=$(brew --prefix openssl@1.1))
args+=(--with-tcltk-libs="$(pkg-config --libs tcl tk)")
args+=(--with-tcltk-includes="$(pkg-config --cflags tcl tk)")
Expand Down Expand Up @@ -768,36 +769,34 @@ elif [ "$OS" == "suse" ]; then
susePrerequisites
fi

openssl
libpng
jpeg
tiff
sqlite
ssh
curl
proj
geotiff

# openssl
#fi
zlib
#openssl
#libpng
#jpeg
#tiff
#sqlite
#ssh
#curl
#proj
#geotiff
##fi
#zlib
pythonVapor
assimp
szip
hdf5
netcdf
expat
udunits
freetype
if [ "$OS" == "Ubuntu" ] ; then
xinerama
fi
ospray
glm
gte
images
qt
#assimp
#szip
#hdf5
#netcdf
#expat
#udunits
#freetype
#if [ "$OS" == "Ubuntu" ] ; then
# xinerama
#fi
#ospray
#glm
#gte
#images
#qt
if [ "$OS" == "macOSx86" ] || [ "$OS" == "M1" ]; then
add_rpath
fi
renameAndCompress
#renameAndCompress
9 changes: 7 additions & 2 deletions site_files/site.NCAR
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ if (UNIX)
if (NOT DEFINED PYTHONVERSION)
set (PYTHONVERSION 3.9)
endif()
set (PYTHONDIR ${THIRD_PARTY_DIR})
set (PYTHONPATH ${THIRD_PARTY_LIB_DIR}/python${PYTHONVERSION})
if ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
set (PYTHONDIR ${THIRD_PARTY_DIR}/Resources/python)
set (PYTHONPATH ${PYTHONDIR}/lib/python${PYTHONVERSION})
else ()
set (PYTHONDIR ${THIRD_PARTY_DIR})
set (PYTHONPATH ${THIRD_PARTY_LIB_DIR}/python${PYTHONVERSION})
endif()
set (EXTRA_LIBS_SEARCH ${EXTRA_LIBS_SEARCH} dbus)
elseif (WIN32)
set (PYTHONVERSION 36)
Expand Down

0 comments on commit fbb9195

Please sign in to comment.