From 76a270bbc5310344b3ccc5b7137c4e393b7d7587 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sat, 1 Jan 2022 17:40:45 -0500 Subject: [PATCH 01/15] On mac arm64 can do a universal2 build for "x86_64 arm64" --- CMakeLists.txt | 14 +++++++++-- bldnrnmacpkgcmake.sh | 44 ++++++++++++++++++++++++++-------- cmake/MacroHelper.cmake | 20 ++++++++++++++++ src/mac/CMakeLists.txt | 9 +++++-- src/mac/activate-apps-cmake.sh | 11 ++++++++- 5 files changed, 83 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6916fa0ebc..e4b4086c3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,9 @@ endif() # Enable MPI # ============================================================================= if(NRN_ENABLE_MPI) - find_package(MPI REQUIRED) + + # find_package(MPI REQUIRED) has a CMAKE_OSX_ARCHITECTURES edge case + NRN_MPI_FIND_PACKAGE() set(NRNMPI 1) set(PARANEURON 1) # avoid linking to C++ bindings @@ -435,7 +437,7 @@ else() endif() # ============================================================================= -# Add helpder CMake modules AFTER setting options +# Add helper CMake modules AFTER setting options # ============================================================================= include(NeuronFileLists) include(MPIDynamicHelper) @@ -643,6 +645,11 @@ file(COPY ${NRN_HEADERS_PATHS} ${PROJECT_BINARY_DIR}/src/oc/nrnpthread.h DESTINATION ${PROJECT_BINARY_DIR}/include) install(DIRECTORY ${PROJECT_BINARY_DIR}/include DESTINATION ${CMAKE_INSTALL_PREFIX}) +if (NRN_MACOS_BUILD) + # universal build for neurondemo needs to be after, or at end of, install + NRN_MACOS_AFTER_INSTALL() +endif() + # ============================================================================= # Copy bash executable for windows # ============================================================================= @@ -785,6 +792,9 @@ if(NRN_ENABLE_CORENEURON) message(STATUS " Legacy Units| ${CORENRN_ENABLE_LEGACY_UNITS}") endif() endif() +if (NRN_UNIVERSAL2_BUILD) + message(STATUS "CMAKE_OSX_A...| ${CMAKE_OSX_ARCHITECTURES}") +endif() if(NRN_ENABLE_COVERAGE) message(STATUS "Coverage | Enabled") if (NRN_COVERAGE_FILES) diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index b5da003161..08c0ad7c82 100755 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -1,18 +1,22 @@ #!/bin/bash set -ex + +default_pythons="python3.8 python3.9 python3.10" # distribution built with -# bash bldnrnmacpkgcmake.sh python3.6 python3.7 python3.8 python3.9 -# without args, default is the 5 pythons above. +# bash bldnrnmacpkgcmake.sh +# without args, default are the pythons above. + CPU=`uname -m` +universal="yes" # changes to "no" if not arm64 or any python not universal +if test "$CPU" != "arm64" ; then + universal="no" +fi + args="$*" if test "$args" = "" ; then - if test "$CPU" = "x86_64" ; then - args="python3.6 python3.7 python3.8 python3.9" - else # arm64 - args="python3 python3.9" - fi + args="$default_pythons" fi #10.7 possible if one builds with pythons that are consistent with that. @@ -36,14 +40,26 @@ mkdir -p $NRN_BLD rm -r -f $NRN_BLD/* cd $NRN_BLD -PYVS="py" # will be part of package file name, eg. py-27-35-36-37-38 +PYVS="py" # will be part of package file name, eg. py-37-38-39-310 pythons="" # will be arg value of NRN_PYTHON_DYNAMIC for i in $args ; do PYVER=`$i -c 'from sys import version_info as v ; print (str(v.major) + str(v.minor)); quit()'` PYVS=${PYVS}-${PYVER} pythons="${pythons}${i};" + pypath="`which $i`" + archs="`lipo -archs $pypath" + if test "$archs" != "x86_64 arm64" ; then + universal="no" + fi done +archs_pkg="" # will be part of the package file name, eg. -arm64-x86_64 +archs_cmake="" # arg for CMAKE_OSX_ARCHITECTURES, eg. arm64;x86_64 +if test "$universal" = "yes" ; then + archs_pkg="-arm64-x86_64" + archs_cmake='-DCMAKE_OSX_ARCHITECTURE="arm64;x86_64"' +fi + # The reason for the "-DCMAKE_PREFIX_PATH=/usr/X11" below # is to definitely link against the xquartz.org installation instead # of the one under /opt/homebrew/ (which I think came @@ -57,11 +73,19 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ -DIV_ENABLE_X11_DYNAMIC=ON \ -DNRN_ENABLE_CORENEURON=OFF \ -DNRN_RX3D_OPT_LEVEL=2 \ - -DCMAKE_OSX_ARCHITECTURES="$CPU" \ + $archs_cmake \ -DCMAKE_PREFIX_PATH=/usr/X11 \ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ make -j install + +if test "$universal" = "yes" ; then + _temp="`lipo -archs $NRN_INSTALL/share/nrn/demo/release/arm64/special`" + if test "$_temp" != "x86_64 arm64" ; then + echo "universal build failed. lipo -archs .../special is \"$_temp\" instead of \"x86_64 arm64\"" + exit 1 + fi +fi $NRN_INSTALL/bin/neurondemo -c 'quit()' chk () { @@ -99,7 +123,7 @@ done # upload package to neuron.yale.edu ALPHADIR='hines@neuron.yale.edu:/home/htdocs/ftp/neuron/versions/alpha' describe="`sh $NRN_SRC/nrnversion.sh describe`" -PACKAGE_FULL_NAME=nrn-${describe}-osx-${CPU}-${PYVS}.pkg +PACKAGE_FULL_NAME=nrn-${describe}-osx${archs_pkg}-${PYVS}.pkg PACKATE_DOWNLOAD_NAME=$ALPHADIR/$PACKAGE_FULL_NAME PACKAGE_FILE_NAME=$NRN_BLD/src/mac/build/NEURON.pkg echo " diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index 8017eba812..585aaf00c7 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -257,3 +257,23 @@ macro(nrn_install_dir_symlink source_dir symlink_dir) # create symbolic link install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${source_dir} ${symlink_dir})") endmacro(nrn_install_dir_symlink) + +# ======================================================================== +# There is an edge case to 'find_package(MPI REQUIRED)' in that we can +# still build a universal2 macos package on an arm64 architecture even if +# the mpi library has no slice for x86_64. +# ======================================================================== +macro(NRN_MPI_FIND_PACKAGE) + if ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES + AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES + AND NRN_ENABLE_MPI_DYNAMIC) + set(_temp ${CMAKE_OSX_ARCHITECTURES}) + set(CMAKE_OSX_ARCHITECTURES arm64 CACHE INTERNAL "" FORCE) + find_package(MPI REQUIRED) + set(CMAKE_OSX_ARCHITECTURES ${_temp} CACHE INTERNAL "" FORCE) + set(NRN_UNIVERSAL2_BUILD ON) + else() + find_package(MPI REQUIRED) + endif() +endmacro() + diff --git a/src/mac/CMakeLists.txt b/src/mac/CMakeLists.txt index 048f0059fd..ba21d11d39 100644 --- a/src/mac/CMakeLists.txt +++ b/src/mac/CMakeLists.txt @@ -4,8 +4,13 @@ if (NRN_MACOS_BUILD) # Sets up icons, apps, and activates them - install(CODE - "execute_process(COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/activate-apps-cmake.sh \"x86_64\" \"${CMAKE_INSTALL_PREFIX}\" \"${PROJECT_SOURCE_DIR}\" \"${CMAKE_INSTALL_PREFIX}/lib\")") + # If universal build, definitely needs to run after (or at end of) + # install, so we create a macro and run at end of + # top level CMakeLists.txt + MACRO (NRN_MACOS_AFTER_INSTALL) + install(CODE + "execute_process(COMMAND sh ${PROJECT_SOURCE_DIR}/src/mac/activate-apps-cmake.sh \"x86_64\" \"${CMAKE_INSTALL_PREFIX}\" \"${PROJECT_SOURCE_DIR}\" \"${CMAKE_INSTALL_PREFIX}/lib\" \"${NRN_UNIVERSAL2_BUILD}\")") + ENDMACRO() set(MACPKG_INSTALL_PATH "/Applications/NEURON") if (${CMAKE_INSTALL_PREFIX} STREQUAL ${MACPKG_INSTALL_PATH}) diff --git a/src/mac/activate-apps-cmake.sh b/src/mac/activate-apps-cmake.sh index e7cf9f33e6..c003ee780d 100755 --- a/src/mac/activate-apps-cmake.sh +++ b/src/mac/activate-apps-cmake.sh @@ -26,6 +26,7 @@ CPU=`uname -m` NRN_INSTALL=$2 NRN_SRC=$3 ivlibdir=$4 +NRN_UNIVERSAL_BUILD=$5 export CPU export NRN_SRC NSRC=$NRN_SRC @@ -63,9 +64,17 @@ osascript -e 'tell application "Finder"'\ -e 'set target of Finder window 1 to folder "bin" of folder '"$lst"' of startup disk'\ -e 'end tell' -# force rebuild of the neurondemo +# force rebuild of the neurondemo (perhaps as universal2) DEMO="${NRN_INSTALL}/share/nrn/demo" rm -f -r ${DEMO}/neuron ${DEMO}/release/${CPU} +if test "${NRN_UNIVERSAL_BUILD}" = "ON" ; then + ( + cd ${DEMO}/release + archs='-arch arm64 -arch x86_64' + $NRN_INSTALL/bin/nrnivmodl -incflags "$archs" -loadflags "$archs" + rm -f ${DEMO}/neuron ; touch ${DEMO}/neuron + ) +fi $NRN_INSTALL/bin/neurondemo << here quit() here From f4d0212d29dae71e7b9ff09785646451128f424f Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sat, 1 Jan 2022 20:26:08 -0500 Subject: [PATCH 02/15] fix some typos. bldnrnmacpkgcmake.sh works for universal2 --- bldnrnmacpkgcmake.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index 08c0ad7c82..4a82320865 100755 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -47,7 +47,7 @@ for i in $args ; do PYVS=${PYVS}-${PYVER} pythons="${pythons}${i};" pypath="`which $i`" - archs="`lipo -archs $pypath" + archs="`lipo -archs $pypath`" if test "$archs" != "x86_64 arm64" ; then universal="no" fi @@ -57,7 +57,7 @@ archs_pkg="" # will be part of the package file name, eg. -arm64-x86_64 archs_cmake="" # arg for CMAKE_OSX_ARCHITECTURES, eg. arm64;x86_64 if test "$universal" = "yes" ; then archs_pkg="-arm64-x86_64" - archs_cmake='-DCMAKE_OSX_ARCHITECTURE="arm64;x86_64"' + archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' fi # The reason for the "-DCMAKE_PREFIX_PATH=/usr/X11" below From 48616e9dbe9250c43b0aa895b2f146da4046b0b7 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sun, 2 Jan 2022 13:23:00 -0500 Subject: [PATCH 03/15] doc for universal2 install packages. --- docs/install/install_instructions.md | 60 ++++++++++++++++++++--- docs/install/mac_pkg.md | 73 ++++++++++++++++++---------- 2 files changed, 101 insertions(+), 32 deletions(-) diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index 2825446b90..f1fade2a25 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -17,24 +17,70 @@ pip3 install neuron Python wheels are provided via [pypi.org](https://pypi.org/project/NEURON/). Note that Python2 wheels are provided for the 8.0.x release series exclusively. -Like Windows, you can also use a binary installer to install NEURON. You can download alpha or recent -releases from below URLs: +Like Windows, you can also use a binary installer to install NEURON. +Recent releases are at -* [Alpha releases](https://neuron.yale.edu/ftp/neuron/versions/alpha/) -* [Recent Releases](https://neuron.yale.edu/ftp/neuron/versions/) +* [Recent Releases](https://github.com/neuronsimulator/nrn/releases) + +You can download legacy versions from: + +* [Legacy Versions](https://neuron.yale.edu/ftp/neuron/versions/) -Mac OS installers have name in the format of `nrn--osx-36-37-38-39.pkg`. Like windows -installer, `py-36-37-38-39` string in the installer name indicates that the given installer is +Earlier Mac OS pkg installers have name in the format of +`nrn--osx-36-37-38-39.pkg`. +Like windows installers, +the, `py-36-37-38-39` string in the installer name indicates that the given installer is compatible with Python versions 3.6, 3.7, 3.8 and 3.9. Note that if you double-click the installer then you might see warning like below. In this case you have to right-click on the installer and then click `Open`. You can then see an option to `Open` installer: +The latest Mac OS pkg installers (as of 2022-01-01) are universal2 installers +(for arm64 and x86_64) and extend the name convention to specify which +architectures they run on. +`nrn--osx--py-.pkg` +e.g. +`nrn-8.0a-690-g3ddaecc21-osx-arm64-x86_64-py-38-39-310.pkg` + ![Installer Warning](../_static/osx_installer_warning_solution.png "Mac OS Warning") -This will install NEURON under directory `/Applications/NEURON-/` directory. For GUI support you +The latest pkg installers will install NEURON under the directory `/Applications/NEURON/` directory. +Uninstallng consists of dragging that folder to the trash. For GUI support you have to install [XQuartz](https://www.xquartz.org/) separately. Once you start Terminal application, NEURON binaries (`nrniv`, `neurondemo` etc.) should be available to start. +* Universal2 installers generally "just work" on either an x86_64 or arm64 +architecture. + + ``` + python + from neuron import h + ``` + and ```nrnivmodl``` will by default create an nmodl mechanism library + specifically for the architecture you run on. + + But it may be the case on Apple M1 that you install a python that can + only run as an x86_64 program under Rosetta2. + E.g. The latest Anaconda Python3.9 (though it seems likely that the next + distribution will be universal2). + In this case, if you wish to launch nrniv, force nrniv to launch as an x86_64 + program. E.g. + ``` + arch -arch x86_64 nrniv -python + from neuron import h + ``` + Furthermore, be sure to run nrnivmodl in such a way that it compiles as an + x86_64 library. e.g. + ``` + arch -arch x86_64 nrnivmodl + ``` + although this constructs an arm64 folder, it will compile and link as x86_64. + ``` + % lipo -archs arm64/libnrnmech.dylib + x86_64 + ``` + Note: there is an environment variable called `ARCHPREFERENCE`. See + `man arch`. + #### Linux Like Mac OS, since 7.8.1 release python wheels are provided and you can use `pip` to install NEURON as: diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index 62b89735ee..dff6d460f6 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -1,22 +1,29 @@ Mac Binary Package (Apple M1 and Mac x86_64) ------------------ -Binary packages are built with the ```nrnmacpkgcmake.sh``` script which, -near the end of its operation, -involves code signing, package signing, and notarization. +Macos binary packages are built with the +[bldnrnmacpkgcmake.sh](https://github.com/neuronsimulator/nrn/blob/master/bldnrnmacpkgcmake.sh) +script which, near the end of its operation, +involves code signing, package signing, and notarization. If built on an +Apple M1, the build will be universal2 and work on arm64 and x86_64 architectures. Preparing your Mac development environment for correct functioning of the script requires installing a few extra [Dependencies](#Dependencies) beyond the -[normal user source build](./install_instructions.html#Mac-OS-Depend), obtaining an Apple Developer Program membership, +[normal user source build](./install_instructions.html#Mac-OS-Depend), +obtaining an Apple Developer Program membership, and requesting two signing certificates from Apple. Those actions are described in separate sections below. On an Apple M1, the script, by default, creates, e.g., -```nrn-8.0a-427-g1a80b2cc-osx-arm64-py-38-39.pkg``` -where the information between nrn and osx comes from ```git describe``` +```nrn-8.0a-714-g76a270bbc-osx-arm64-x86_64-py-38-39-310.pkg``` +where the information between nrn and osx comes from ```git describe```, +the item(s) between osx and py indicate the architecures on which +the program can run, and the numbers after the py indicate the python versions that are compatible with this package. Those python versions must be installed on the developer machine. On a Mac x86_64 architecture the script, by default, -creates, e.g., ```nrn-8.0a-427-g1a80b2cc-osx-x86_64-py-27-36-37-38-39.pkg``` +creates, e.g., ```nrn-8.0a-427-g1a80b2cc-osx-x86_64-py-38-39-310.pkg``` +On a Mac arm64 architecture, the script will build a universal pkg only +if all the Python's are themselves universal. A space separated list of python executable arguments can be used in place of the internal default lists. ```$NRN_SRC``` is the location of the @@ -28,22 +35,27 @@ At time of writing, the cmake command in the script that is used to configure the build is ``` cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ - -DNRN_ENABLE_MPI_DYNAMIC=ON \ + -DNRN_ENABLE_MPI_DYNAMIC=ON \ -DPYTHON_EXECUTABLE=`which python3` -DNRN_ENABLE_PYTHON_DYNAMIC=ON \ -DNRN_PYTHON_DYNAMIC="$pythons" \ -DIV_ENABLE_X11_DYNAMIC=ON \ -DNRN_ENABLE_CORENEURON=OFF \ -DNRN_RX3D_OPT_LEVEL=2 \ - -DCMAKE_OSX_ARCHITECTURES="$CPU" \ + $archs_cmake \ + -DCMAKE_PREFIX_PATH=/usr/X11 \ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ``` +An an arm64 the default variables above will be +``` +pythons="python3.8 python3.9 python3.10" +archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' +``` A universal build is possible with ```-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"``` -but the installations for openmpi and python on your machine must also be universal. -I.e. configure with ```-DNRN_ENABLE_MPI_DYNAMIC=OFF -DNRN_PYTHON_DYNAMIC=/usr/bin/python3```. -As we have been unable to find or build a universal openmpi, and -only the Big Sur default Python 3.8 installaion is universal, we are -currently building separate installers for arm64 and x86_64. +but the installations of python on your machine must also be universal. +The MPI library does not have to be universal if configuring with +```-DNRN_ENABLE_MPI_DYNAMIC=ON``` as the library is not linked against +during the build. ```make -j install``` is used to build and install in ```/Applications/NEURON``` @@ -73,6 +85,12 @@ currently building separate installers for arm64 and x86_64. - request Apple to notarize NEURON.pkg ```src/macnrn_notarize.sh``` + If notatarizaton fails, it is occasionally due to Apple + changing the contracts and demanding that + "You must first sign the relevant contracts online. (1048)". In that + case, go to [appstoreconnect.apple.com](https://appstoreconnect.apple.com + to accept the legal docs. + The script ends by printing: ``` Until we figure out how to automatically staple the notarization @@ -100,25 +118,28 @@ x86_64 arm64 ``` which is generally the case for all Big Sur mac software. On the other hand, ```brew install ...``` executables and libraries are -generally only for the architecture indicated by -``` -uname -m -``` +generally only for the architecture indicated by ```uname -m```. That is +ok for openmpi but since the various python libraries are linked against +during build to create the version specific neuron modules, those python +installers also have to be universal. Fortunately, universal python versions +can be found at [python.org](http://python.org/Downloads/macOS) at least for +(as of 2022-01-01) python3.8, python3.9, and python3.10. - ```xcode-select --install```: - Sadly, notarization requires ```altool``` which is not distributed with the command line tools. So one needs to install the full xcode (at least version 12) from the App Store. That is very large and may - take an hour or so to download. + take an hour or so to download. (should be checked to see if this is + still the case.) - Install latest [XQuartz](http://xquartz.org) release. At least XQuartz-2.8.0_rc1 - Install [PackagesBuild](http://s.sudre.free.fr/Software/Packages/about.html) -- ```brew install cmake open-mpi python3.9``` +- ```brew install coreutils cmake bison flex open-mpi``` - - Python 3.8 is already installed as /usr/bin/python3 + - Python 3.8 is already installed as /usr/bin/python3 and is universal2. - The [normal source build](./install_instructions.html#Mac-OS-Depend) explains how to install brew and add it to the PATH. @@ -128,15 +149,17 @@ uname -m eval $(/opt/homebrew/bin/brew shellenv) ``` - - Both pythons need numpy installed + - Default build uses universal pythons from python.org. I also redundantly + include their python3.8 as I find it more convenient to be able to + explicitly specify the full name as python3.8. + + - All pythons used for building need numpy installed, e.g. ``` pip3.9 install --user --upgrade pip pip3.9 install --user numpy - python3 -m pip install --user --upgrade pip - python3 -m pip install --user numpy ``` - - At least the first python3 in your PATH needs cython installed + - At least one python3 in your PATH needs cython installed ``` python3 -m pip install --user cython ``` From e81e026fabac6ef60697a8a5cea1e0eb7ff0cf3c Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sun, 2 Jan 2022 17:07:35 -0500 Subject: [PATCH 04/15] macOS,arm64 stderr message if mismatched arch for dlopen. --- docs/install/install_instructions.md | 10 ++++++++ src/nrniv/nrnpy.cpp | 6 +++++ src/nrnmpi/nrnmpi_dynam.cpp | 9 ++++++- src/nrnoc/init.cpp | 37 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index f1fade2a25..5c0cacc5da 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -78,6 +78,16 @@ architecture. % lipo -archs arm64/libnrnmech.dylib x86_64 ``` + + If, at runtime there is architecture mismatch between python, MPI, + libnrnmech.so, or libnrniv.dylib, you will see an error message similar + to + ``` + Could not dlopen NRN_PYLIB: /Users/hines/opt/anaconda3/lib/libpython3.9.dylib + libnrniv.dylib running as arm64 + but /Users/hines/opt/anaconda3/lib/libpython3.9.dylib can only run as x86_64 + ``` + Note: there is an environment variable called `ARCHPREFERENCE`. See `man arch`. diff --git a/src/nrniv/nrnpy.cpp b/src/nrniv/nrnpy.cpp index 962721caaf..e03cd51d6a 100644 --- a/src/nrniv/nrnpy.cpp +++ b/src/nrniv/nrnpy.cpp @@ -24,6 +24,9 @@ static void (*p_nrnpython_real)(); static void (*p_nrnpython_reg_real)(); extern "C" char* hoc_back2forward(char* s); char* hoc_forward2back(char* s); +#if DARWIN +extern void nrn_possible_mismatched_arch(const char*); +#endif // following is undefined or else has the value of sys.api_version // at time of configure (using the python first in the PATH). @@ -230,6 +233,9 @@ void nrnpython_reg() { handle = dlopen(nrnpy_pylib, RTLD_NOW|RTLD_GLOBAL); if (!handle) { fprintf(stderr, "Could not dlopen NRN_PYLIB: %s\n", nrnpy_pylib); +#if DARWIN + nrn_possible_mismatched_arch(nrnpy_pylib); +#endif exit(1); } } diff --git a/src/nrnmpi/nrnmpi_dynam.cpp b/src/nrnmpi/nrnmpi_dynam.cpp index 533ba6f757..a8b0ba2a6d 100644 --- a/src/nrnmpi/nrnmpi_dynam.cpp +++ b/src/nrnmpi/nrnmpi_dynam.cpp @@ -28,6 +28,10 @@ extern char* dlerror(); extern char* cxx_char_alloc(size_t); extern std::string corenrn_mpi_library; +#if DARWIN +extern void nrn_possible_mismatched_arch(const char*); +#endif + #if DARWIN || defined(__linux__) extern const char* path_prefix_to_libnrniv(); #endif @@ -44,6 +48,9 @@ static void* load_mpi(const char* name, char* mes) { int flag = RTLD_NOW | RTLD_GLOBAL; void* handle = dlopen(name, flag); if (!handle) { +#if DARWIN + nrn_possible_mismatched_arch(name); +#endif sprintf(mes, "load_mpi: %s\n", dlerror()); }else{ sprintf(mes, "load_mpi: %s successful\n", name); @@ -99,7 +106,7 @@ char* nrnmpi_load(int is_python) { if (mpi_lib_path) { handle = load_mpi(mpi_lib_path, pmes+strlen(pmes)); if (!handle) { - sprintf(pmes, "Can not load libmpi.dylib and %s", mpi_lib_path); + sprintf(pmes, "Can not load libmpi.dylib and %s\n", mpi_lib_path); } } } diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index 270fa2576b..f345ff5bdd 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -57,6 +57,35 @@ extern int nrn_noauto_dlopen_nrnmech; /* default 0 declared in hoc_init.cpp */ #define DLL_DEFAULT_FNAME "libnrnmech.dylib" #endif +// error message hint with regard to mismatched arch +void nrn_possible_mismatched_arch(const char* libname) { + if (strncmp(NRNHOSTCPU, "arm64", 5) == 0) { + // what arch are we running on +#if __arm64__ + const char* we_are{"arm64"}; +#elif __x86_64__ + const char* we_are{"x86_64"}; +#endif + + // what arch did we try to dlopen + char* cmd; + cmd = new char[strlen(libname) + 100]; + sprintf(cmd, "lipo -archs %s 2> /dev/null", libname); + char libname_arch[20]{0}; + FILE* p = popen(cmd, "r"); + delete [] cmd; + if (!p) { return; } + fgets(libname_arch, 18, p); + if (strlen(libname_arch) == 0) {return;} + pclose(p); + + if (strstr(libname_arch, we_are) == NULL) { + fprintf(stderr, "libnrniv.dylib running as %s\n", we_are); + fprintf(stderr, "but %s can only run as %s\n", libname, libname_arch); + } + } +} + #if __GNUC__ < 4 #include "osxdlfcn.h" #include "osxdlfcn.cpp" @@ -230,12 +259,20 @@ void* nrn_realpath_dlopen(const char* relpath, int flags) { #endif /* not HAVE_REALPATH */ if (abspath) { handle = dlopen(abspath, flags); +#if DARWIN + if (!handle) { + nrn_possible_mismatched_arch(abspath); + } +#endif free(abspath); }else{ int patherr = errno; handle = dlopen(relpath, flags); if (!handle) { Fprintf(stderr, "realpath failed errno=%d (%s) and dlopen failed with %s\n", patherr, strerror(patherr), relpath); +#if DARWIN + nrn_possible_mismatched_arch(abspath); +#endif } } return handle; From 6e80a61cf3ddfa8de683db3e88e79189658a088d Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sun, 2 Jan 2022 20:35:14 -0500 Subject: [PATCH 05/15] Some doc details about notarization. --- docs/install/mac_pkg.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index dff6d460f6..bb3d2495ab 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -85,11 +85,28 @@ during the build. - request Apple to notarize NEURON.pkg ```src/macnrn_notarize.sh``` - If notatarizaton fails, it is occasionally due to Apple + If notarizaton fails, it is occasionally due to Apple changing the contracts and demanding that "You must first sign the relevant contracts online. (1048)". In that - case, go to [appstoreconnect.apple.com](https://appstoreconnect.apple.com - to accept the legal docs. + case, go to [appstoreconnect.apple.com](https://appstoreconnect.apple.com) + to accept the legal docs. For other notarization failures, one must consult + the LogFileURL which can be obtained with + ``` + % xcrun altool --notarization-info $RequestIdentifier \ + --username "michael.hines@yale.edu" \ + --password "`cat ~/.ssh/notarization-password`" + No errors getting notarization info. + + Date: 2022-01-02 23:38:12 +0000 + Hash: 7254157952d4f3573c2804879cf6da8d... + LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets... + RequestUUID: 152f0f0e-af58-4d22-b291-6a441825dd20 + Status: invalid + Status Code: 2 + Status Message: Package Invalid + ``` + where RequestIdentifer (the RequestUUID) appears in the email sent + back in response to the notarization request. The script ends by printing: ``` From d29db7a98741c20c7d010251ae0265b255a21cc1 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Sun, 2 Jan 2022 21:16:55 -0500 Subject: [PATCH 06/15] Update mac_pkg.md --- docs/install/mac_pkg.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index bb3d2495ab..a72854ded7 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -16,7 +16,7 @@ On an Apple M1, the script, by default, creates, e.g., ```nrn-8.0a-714-g76a270bbc-osx-arm64-x86_64-py-38-39-310.pkg``` where the information between nrn and osx comes from ```git describe```, -the item(s) between osx and py indicate the architecures on which +the item(s) between osx and py indicate the architectures on which the program can run, and the numbers after the py indicate the python versions that are compatible with this package. Those python versions must be installed on @@ -45,7 +45,7 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ -DCMAKE_PREFIX_PATH=/usr/X11 \ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ``` -An an arm64 the default variables above will be +On an arm64 the default variables above will be ``` pythons="python3.8 python3.9 python3.10" archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' From 0de4d4b8e9d426f53e5948f3ca1a2d40f2889aab Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Tue, 4 Jan 2022 09:39:09 -0500 Subject: [PATCH 07/15] macOS x86_64 machine can also build a universal2 package. --- CMakeLists.txt | 2 +- bldnrnmacpkgcmake.sh | 7 ++----- cmake/MacroHelper.cmake | 4 ++-- docs/install/install_instructions.md | 4 ++++ docs/install/mac_pkg.md | 19 ++++++++++--------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4b4086c3a..9adc1223c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,7 +300,7 @@ endif() if(NRN_ENABLE_MPI) # find_package(MPI REQUIRED) has a CMAKE_OSX_ARCHITECTURES edge case - NRN_MPI_FIND_PACKAGE() + nrn_mpi_find_package() set(NRNMPI 1) set(PARANEURON 1) # avoid linking to C++ bindings diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index 4a82320865..f3782c863f 100755 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -9,10 +9,7 @@ default_pythons="python3.8 python3.9 python3.10" CPU=`uname -m` -universal="yes" # changes to "no" if not arm64 or any python not universal -if test "$CPU" != "arm64" ; then - universal="no" -fi +universal="yes" # changes to "no" if any python not universal args="$*" if test "$args" = "" ; then @@ -80,7 +77,7 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ make -j install if test "$universal" = "yes" ; then - _temp="`lipo -archs $NRN_INSTALL/share/nrn/demo/release/arm64/special`" + _temp="`lipo -archs $NRN_INSTALL/share/nrn/demo/release/$CPU/special`" if test "$_temp" != "x86_64 arm64" ; then echo "universal build failed. lipo -archs .../special is \"$_temp\" instead of \"x86_64 arm64\"" exit 1 diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index 585aaf00c7..adf7e3a749 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -263,12 +263,12 @@ endmacro(nrn_install_dir_symlink) # still build a universal2 macos package on an arm64 architecture even if # the mpi library has no slice for x86_64. # ======================================================================== -macro(NRN_MPI_FIND_PACKAGE) +macro(nrn_mpi_find_package) if ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES AND NRN_ENABLE_MPI_DYNAMIC) set(_temp ${CMAKE_OSX_ARCHITECTURES}) - set(CMAKE_OSX_ARCHITECTURES arm64 CACHE INTERNAL "" FORCE) + unset(CMAKE_OSX_ARCHITECTURES CACHE) find_package(MPI REQUIRED) set(CMAKE_OSX_ARCHITECTURES ${_temp} CACHE INTERNAL "" FORCE) set(NRN_UNIVERSAL2_BUILD ON) diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index 5c0cacc5da..8382db4b90 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -78,6 +78,10 @@ architecture. % lipo -archs arm64/libnrnmech.dylib x86_64 ``` + Alternatively, one can get a universal2 result with + ``` + nrnivmodl -incflags '-arch x86_64 -arch arm64' -loadflags '-arch x86_64 -arch arm64' + ``` If, at runtime there is architecture mismatch between python, MPI, libnrnmech.so, or libnrniv.dylib, you will see an error message similar diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index a72854ded7..020bcd8e0d 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -4,15 +4,16 @@ Mac Binary Package (Apple M1 and Mac x86_64) Macos binary packages are built with the [bldnrnmacpkgcmake.sh](https://github.com/neuronsimulator/nrn/blob/master/bldnrnmacpkgcmake.sh) script which, near the end of its operation, -involves code signing, package signing, and notarization. If built on an -Apple M1, the build will be universal2 and work on arm64 and x86_64 architectures. +involves code signing, package signing, and notarization. +The build will be universal2 and work on arm64 and x86_64 architectures +(if the pythons used are themselves, universal2). Preparing your Mac development environment for correct functioning of the script requires installing a few extra [Dependencies](#Dependencies) beyond the [normal user source build](./install_instructions.html#Mac-OS-Depend), obtaining an Apple Developer Program membership, and requesting two signing certificates from Apple. Those actions are described in separate sections below. -On an Apple M1, +On an Apple M1 or x86_64, the script, by default, creates, e.g., ```nrn-8.0a-714-g76a270bbc-osx-arm64-x86_64-py-38-39-310.pkg``` where the information between nrn and osx comes from ```git describe```, @@ -20,9 +21,8 @@ the item(s) between osx and py indicate the architectures on which the program can run, and the numbers after the py indicate the python versions that are compatible with this package. Those python versions must be installed on -the developer machine. On a Mac x86_64 architecture the script, by default, -creates, e.g., ```nrn-8.0a-427-g1a80b2cc-osx-x86_64-py-38-39-310.pkg``` -On a Mac arm64 architecture, the script will build a universal pkg only +the developer machine. +The script will build a universal pkg only if all the Python's are themselves universal. A space separated list of python executable arguments can be used in @@ -45,7 +45,7 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$NRN_INSTALL \ -DCMAKE_PREFIX_PATH=/usr/X11 \ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ``` -On an arm64 the default variables above will be +The default variables above will be ``` pythons="python3.8 python3.9 python3.10" archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' @@ -176,9 +176,10 @@ can be found at [python.org](http://python.org/Downloads/macOS) at least for pip3.9 install --user numpy ``` - - At least one python3 in your PATH needs cython installed + - At least one python3 in your PATH needs cython installed. + And, to avoid compile errors, the minimum version is 0.29.26 ``` - python3 -m pip install --user cython + python3.10 -m pip install --user cython ``` #### Signing and Notarization From 9c4cb48819520c437bd96d09e86e9c1b25810e0c Mon Sep 17 00:00:00 2001 From: nrnhines Date: Wed, 5 Jan 2022 06:33:30 -0500 Subject: [PATCH 08/15] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexandru Săvulescu --- CMakeLists.txt | 4 ++-- src/mac/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9ccc902a..21ece440e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -647,7 +647,7 @@ install(DIRECTORY ${PROJECT_BINARY_DIR}/include DESTINATION ${CMAKE_INSTALL_PREF if (NRN_MACOS_BUILD) # universal build for neurondemo needs to be after, or at end of, install - NRN_MACOS_AFTER_INSTALL() + nrn_macos_after_install() endif() # ============================================================================= @@ -793,7 +793,7 @@ if(NRN_ENABLE_CORENEURON) endif() endif() if (NRN_UNIVERSAL2_BUILD) - message(STATUS "CMAKE_OSX_A...| ${CMAKE_OSX_ARCHITECTURES}") + message(STATUS "CMAKE_OSX_ARCH| ${CMAKE_OSX_ARCHITECTURES}") endif() message(STATUS "Tests | ${NRN_ENABLE_TESTS}") if(NRN_ENABLE_COVERAGE) diff --git a/src/mac/CMakeLists.txt b/src/mac/CMakeLists.txt index ba21d11d39..44be774b01 100644 --- a/src/mac/CMakeLists.txt +++ b/src/mac/CMakeLists.txt @@ -7,10 +7,10 @@ if (NRN_MACOS_BUILD) # If universal build, definitely needs to run after (or at end of) # install, so we create a macro and run at end of # top level CMakeLists.txt - MACRO (NRN_MACOS_AFTER_INSTALL) + macro(nrn_macos_after_install) install(CODE "execute_process(COMMAND sh ${PROJECT_SOURCE_DIR}/src/mac/activate-apps-cmake.sh \"x86_64\" \"${CMAKE_INSTALL_PREFIX}\" \"${PROJECT_SOURCE_DIR}\" \"${CMAKE_INSTALL_PREFIX}/lib\" \"${NRN_UNIVERSAL2_BUILD}\")") - ENDMACRO() + endmacro() set(MACPKG_INSTALL_PATH "/Applications/NEURON") if (${CMAKE_INSTALL_PREFIX} STREQUAL ${MACPKG_INSTALL_PATH}) From be6255a3635ffa5e4eaf9ddf278dc6257ea6f8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20S=C4=83vulescu?= Date: Wed, 5 Jan 2022 12:47:31 +0100 Subject: [PATCH 09/15] fix brew install instructions --- docs/install/mac_pkg.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index 020bcd8e0d..8ed935737e 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -160,8 +160,8 @@ can be found at [python.org](http://python.org/Downloads/macOS) at least for - The [normal source build](./install_instructions.html#Mac-OS-Depend) explains how to install brew and add it to the PATH. - ``` - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/H$ + ```bash + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> $HOME/.zprofile eval $(/opt/homebrew/bin/brew shellenv) ``` From 54e9009fd089d4f1e9dd71dd757f9343bfcd50cd Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Wed, 5 Jan 2022 09:07:04 -0500 Subject: [PATCH 10/15] MACOSX_DEPLOYMENT_TARGET=11 --- bldnrnmacpkgcmake.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index f3782c863f..f0f706d6d6 100755 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -17,9 +17,7 @@ if test "$args" = "" ; then fi #10.7 possible if one builds with pythons that are consistent with that. -if test "$CPU" = "x86_64" ; then - export MACOSX_DEPLOYMENT_TARGET=10.9 -fi +export MACOSX_DEPLOYMENT_TARGET=11 if test "$NRN_SRC" == "" ; then NRN_SRC=$HOME/neuron/nrn From b9a811a324770b11212fbe327d9540d2f1ddc69c Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Fri, 7 Jan 2022 12:02:04 -0500 Subject: [PATCH 11/15] macos version appears in installer name --- bldnrnmacpkgcmake.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index f0f706d6d6..5dd3561bea 100755 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -118,7 +118,8 @@ done # upload package to neuron.yale.edu ALPHADIR='hines@neuron.yale.edu:/home/htdocs/ftp/neuron/versions/alpha' describe="`sh $NRN_SRC/nrnversion.sh describe`" -PACKAGE_FULL_NAME=nrn-${describe}-osx${archs_pkg}-${PYVS}.pkg +macos=macos${MACOSX_DEPLOYMENT_TARGET} +PACKAGE_FULL_NAME=nrn-${describe}-${macos}${archs_pkg}-${PYVS}.pkg PACKATE_DOWNLOAD_NAME=$ALPHADIR/$PACKAGE_FULL_NAME PACKAGE_FILE_NAME=$NRN_BLD/src/mac/build/NEURON.pkg echo " From 2e4e3a2087e599b5c0ac502fb02a38304086ec63 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Fri, 7 Jan 2022 16:01:39 -0500 Subject: [PATCH 12/15] update macos instructions --- docs/install/install_instructions.md | 15 ++++++++++++--- docs/install/mac_pkg.md | 11 +++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index 8382db4b90..abfa568102 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -37,9 +37,9 @@ click `Open`. You can then see an option to `Open` installer: The latest Mac OS pkg installers (as of 2022-01-01) are universal2 installers (for arm64 and x86_64) and extend the name convention to specify which architectures they run on. -`nrn--osx--py-.pkg` +`nrn--macos--py-.pkg` e.g. -`nrn-8.0a-690-g3ddaecc21-osx-arm64-x86_64-py-38-39-310.pkg` +`nrn-8.0a-726-gb9a811a32-macos11-arm64-x86_64-py-38-39-310.pkg` ![Installer Warning](../_static/osx_installer_warning_solution.png "Mac OS Warning") @@ -95,6 +95,15 @@ architecture. Note: there is an environment variable called `ARCHPREFERENCE`. See `man arch`. + It may be the case on an x86_64 that if you have an older x86_64 + version of python3.8 or 3.9 installed that those versions of python + are for macos earlier than 11. In that case, you may get a warning of + the form `warning: ... built for newer macOS version (11.0) than being linked (10.9)` + One work around is to install a more recent python or a python with a + more recent build. For example, the package installers at [python.org](http://python.org) + contain the "macos11" string within the package name for the universal2 + installers for python 3.8, 3.9, and 3.10. + #### Linux Like Mac OS, since 7.8.1 release python wheels are provided and you can use `pip` to install NEURON as: @@ -222,7 +231,7 @@ export PATH=/usr/local/bin/:$PATH ``` If the desired python version is not installed, you can install it using -[official distribution](https://www.python.org/downloads/mac-osx/). Also, note that +[official distribution](https://www.python.org/downloads/macos/). Also, note that [Xcode Command Line Tools](https://stackoverflow.com/questions/9329243/how-to-install-xcode-command-line-tools) needs to be installed for development. diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index 8ed935737e..b7fee471bc 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -15,15 +15,18 @@ and requesting two signing certificates from Apple. Those actions are described in separate sections below. On an Apple M1 or x86_64, the script, by default, creates, e.g., -```nrn-8.0a-714-g76a270bbc-osx-arm64-x86_64-py-38-39-310.pkg``` -where the information between nrn and osx comes from ```git describe```, -the item(s) between osx and py indicate the architectures on which -the program can run, +```nrn-8.0a-726-gb9a811a32-macos11-arm64-x86_64-py-38-39-310.pkg``` +where the information between nrn and macos comes from ```git describe```, +the number after macos refers to the ```MACOSX_DEPLOYMENT_TARGET=11``` +the next item(s) before py indicate the architectures on which +the program can run (```arm64-x86_64```) and the numbers after the py indicate the python versions that are compatible with this package. Those python versions must be installed on the developer machine. The script will build a universal pkg only if all the Python's are themselves universal. +Presently, one must manually make sure that all the python builds used +the same MACOSX_DEPLOYMENT_TARGET. A space separated list of python executable arguments can be used in place of the internal default lists. ```$NRN_SRC``` is the location of the From 93c9d91aad3882222d9698177243ed96eee3ab1b Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Sun, 16 Jan 2022 16:11:53 -0500 Subject: [PATCH 13/15] Choose MACOSX_DEPLOYMENT_TARGET consistent with all Pythons --- bldnrnmacpkgcmake.sh | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) mode change 100755 => 100644 bldnrnmacpkgcmake.sh diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh old mode 100755 new mode 100644 index 5dd3561bea..f99cd73559 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -6,6 +6,10 @@ default_pythons="python3.8 python3.9 python3.10" # bash bldnrnmacpkgcmake.sh # without args, default are the pythons above. +# If all the pythons are universal, then so is NEURON. +# Otherwise $CPU +# All pythons must have the same macos version and that will become +# the MACOSX_DEPLOYMENT_TARGET CPU=`uname -m` @@ -16,8 +20,22 @@ if test "$args" = "" ; then args="$default_pythons" fi -#10.7 possible if one builds with pythons that are consistent with that. -export MACOSX_DEPLOYMENT_TARGET=11 + +# Choose MACOSX_DEPLOYMENT_TARGET consistent with all Pythons +macosver="" +for i in $args ; do + mver=`$i -c 'import sysconfig; print(sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")); quit()'` + echo "macos version for $i is $mver" + if test "$macosver" = "" ; then + macosver=$mver + fi + if test "$macosver" != "$mver" ; then + echo "$i macos $mver differs from previous python macos $macosver" + exit 1 + fi +done +export MACOSX_DEPLOYMENT_TARGET=$macosver +echo "MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET" if test "$NRN_SRC" == "" ; then NRN_SRC=$HOME/neuron/nrn @@ -55,6 +73,8 @@ if test "$universal" = "yes" ; then archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' fi +echo "archs_pkg=$archs_pkg" + # The reason for the "-DCMAKE_PREFIX_PATH=/usr/X11" below # is to definitely link against the xquartz.org installation instead # of the one under /opt/homebrew/ (which I think came From 11e50b1cb5286aaec110b033de484546bc89c335 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Wed, 23 Feb 2022 12:47:32 -0500 Subject: [PATCH 14/15] use sysconfig.get_platform() to determine name of pkg file. --- bldnrnmacpkgcmake.sh | 38 +++++++++++++++------------- docs/install/install_instructions.md | 7 ++--- docs/install/mac_pkg.md | 10 +++++--- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/bldnrnmacpkgcmake.sh b/bldnrnmacpkgcmake.sh index 51faae0e4d..e29c3f7738 100644 --- a/bldnrnmacpkgcmake.sh +++ b/bldnrnmacpkgcmake.sh @@ -21,19 +21,30 @@ if test "$args" = "" ; then fi -# Choose MACOSX_DEPLOYMENT_TARGET consistent with all Pythons -macosver="" +# sysconfig.get_platform() looks like, e.g. "macosx-12.2-arm64" or +# "macosx-11-universal2". I.e. encodes MACOSX_DEPLOYMENT_TARGET and archs. +# Demand all pythons we are building against have same platform. +mac_platform="" for i in $args ; do - mver=`$i -c 'import sysconfig; print(sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")); quit()'` - echo "macos version for $i is $mver" - if test "$macosver" = "" ; then - macosver=$mver + last_py=$i + mplat=`$i -c 'import sysconfig; print(sysconfig.get_platform())'` + echo "platform for $i is $mplat" + if test "$mac_platform" = "" ; then + mac_platform=$mplat fi - if test "$macosver" != "$mver" ; then - echo "$i macos $mver differs from previous python macos $macosver" + if test "$mac_platform" != "$mplat" ; then + echo "$i platform \"$mplat\" differs from previous python \"$mac_platform\"." exit 1 fi done + +# extract MACOSX_DEPLOYMENT_TARGET and archs from mac_platform +macosver=`$last_py -c 'import sysconfig; print(sysconfig.get_platform().split("-")[1])'` +archs=`$last_py -c 'import sysconfig; print(sysconfig.get_platform().split("-")[2])'` +if test "$archs" != "universal2" ; then + universal=no +fi + export MACOSX_DEPLOYMENT_TARGET=$macosver echo "MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET" @@ -59,22 +70,13 @@ for i in $args ; do PYVER=`$i -c 'from sys import version_info as v ; print (str(v.major) + str(v.minor)); quit()'` PYVS=${PYVS}-${PYVER} pythons="${pythons}${i};" - pypath="`which $i`" - archs="`lipo -archs $pypath`" - if test "$archs" != "x86_64 arm64" ; then - universal="no" - fi done -archs_pkg="" # will be part of the package file name, eg. -arm64-x86_64 archs_cmake="" # arg for CMAKE_OSX_ARCHITECTURES, eg. arm64;x86_64 if test "$universal" = "yes" ; then - archs_pkg="-arm64-x86_64" archs_cmake='-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' fi -echo "archs_pkg=$archs_pkg" - # The reason for the "-DCMAKE_PREFIX_PATH=/usr/X11" below # is to definitely link against the xquartz.org installation instead # of the one under /opt/homebrew/ (which I think came @@ -139,7 +141,7 @@ done ALPHADIR='hines@neuron.yale.edu:/home/htdocs/ftp/neuron/versions/alpha' describe="`sh $NRN_SRC/nrnversion.sh describe`" macos=macos${MACOSX_DEPLOYMENT_TARGET} -PACKAGE_FULL_NAME=nrn-${describe}-${macos}${archs_pkg}-${PYVS}.pkg +PACKAGE_FULL_NAME=nrn-${describe}-${mac_platform}-${PYVS}.pkg PACKATE_DOWNLOAD_NAME=$ALPHADIR/$PACKAGE_FULL_NAME PACKAGE_FILE_NAME=$NRN_BLD/src/mac/build/NEURON.pkg echo " diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index abfa568102..5207e32bab 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -36,10 +36,11 @@ click `Open`. You can then see an option to `Open` installer: The latest Mac OS pkg installers (as of 2022-01-01) are universal2 installers (for arm64 and x86_64) and extend the name convention to specify which -architectures they run on. -`nrn--macos--py-.pkg` +architectures they run on and the minimum macosx version using the same +style as the python `sysconfig.get_platform()` +`nrn--macosx---py-.pkg` e.g. -`nrn-8.0a-726-gb9a811a32-macos11-arm64-x86_64-py-38-39-310.pkg` +`nrn-8.0a-726-gb9a811a32-macosx-11-universal2-py-38-39-310.pkg` ![Installer Warning](../_static/osx_installer_warning_solution.png "Mac OS Warning") diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index b7fee471bc..38d77d1609 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -15,18 +15,20 @@ and requesting two signing certificates from Apple. Those actions are described in separate sections below. On an Apple M1 or x86_64, the script, by default, creates, e.g., -```nrn-8.0a-726-gb9a811a32-macos11-arm64-x86_64-py-38-39-310.pkg``` -where the information between nrn and macos comes from ```git describe```, +```nrn-8.0a-726-gb9a811a32-macosx-11-universal2-py-38-39-310.pkg``` +where the information between nrn and macosx comes from ```git describe```, the number after macos refers to the ```MACOSX_DEPLOYMENT_TARGET=11``` the next item(s) before py indicate the architectures on which -the program can run (```arm64-x86_64```) +the program can run (i.e. ```arm64```, ```x86_64```, or ```universal2``` +for both) and the numbers after the py indicate the python versions that are compatible with this package. Those python versions must be installed on the developer machine. The script will build a universal pkg only if all the Python's are themselves universal. Presently, one must manually make sure that all the python builds used -the same MACOSX_DEPLOYMENT_TARGET. +the same MACOSX_DEPLOYMENT_TARGET. You can check both of these with +```python3 -c 'import sysconfig; print(sysconfig.get_platform())'``` A space separated list of python executable arguments can be used in place of the internal default lists. ```$NRN_SRC``` is the location of the From a09fe2052af3c9b0dbf4aef659420aa8a2dc6a11 Mon Sep 17 00:00:00 2001 From: Michael Hines Date: Wed, 23 Feb 2022 19:56:42 -0500 Subject: [PATCH 15/15] Latest mingw changed location of crtbegin.o --- mingw_files/nrnmingwenv.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mingw_files/nrnmingwenv.sh b/mingw_files/nrnmingwenv.sh index 2d0493ee69..9e7fe60437 100644 --- a/mingw_files/nrnmingwenv.sh +++ b/mingw_files/nrnmingwenv.sh @@ -149,7 +149,11 @@ unistd.h vadefs.h ' -copy mingw64/x86_64-w64-mingw32/lib ' +mlib=mingw64/x86_64-w64-mingw32/lib # gcc 11.2.0 Rev 1 +if test -f /mingw64/lib/dllcrt2.o ; then # gcc 11.2.0 Rev 9 + mlib=mingw64/lib +fi +copy $mlib ' crtbegin.o crtend.o dllcrt2.o