diff --git a/.gitignore b/.gitignore index 540839f1c..a75bb3453 100644 --- a/.gitignore +++ b/.gitignore @@ -23,10 +23,12 @@ /matlab/supported_octave_version.m # Created by the macOS package build script -/macOS/deps/sources64/ +/macOS/deps/arm64/sources64/ +/macOS/deps/x86_64/sources64/ /macOS/deps/tarballs/ -/macOS/deps/lib64/ +/macOS/deps/arm64/lib64/ +/macOS/deps/x86_64/lib64/ +build-doc # Emacs stuff scripts/dynare.elc - diff --git a/README.md b/README.md index ad50e2a4c..bc19b880a 100644 --- a/README.md +++ b/README.md @@ -476,7 +476,7 @@ You can also choose a specific version of Dynare by checking out the correspondi - Configure Dynare from the source directory: ```sh -arch -$ARCH meson setup --native-file scripts/homebrew-native.ini -Dmatlab_path=/Applications/MATLAB_R2022b_Beta.app -Dbuildtype=debugoptimized -Dfortran_args="['-B','$DYNAREDIR/slicot/lib']" build-matlab +arch -$ARCH meson setup --native-file scripts/homebrew-native-$ARCH.ini -Dmatlab_path=/Applications/MATLAB_R2022b_Beta.app -Dbuildtype=debugoptimized -Dfortran_args="['-B','$DYNAREDIR/slicot/lib']" build-matlab ``` where you need to adapt the path to MATLAB. Similarly, if you don't want to compile for Octave, replace the `-Dmatlab_path` option by `-Dbuild_for=octave`, and change the build directory to `build-octave`. diff --git a/macOS/Makefile b/macOS/Makefile index 3a51bd58a..e331abef2 100644 --- a/macOS/Makefile +++ b/macOS/Makefile @@ -15,22 +15,28 @@ # You should have received a copy of the GNU General Public License # along with Dynare. If not, see . -.PHONY: all deps clean-deps clean clean-all build +ARCHS = arm64 x86_64 +BUILDS = $(addprefix build-, $(ARCHS)) +DEPS = $(addprefix deps-, $(ARCHS)) +CLEAN_DEPS = $(addprefix clean-deps-, $(ARCHS)) +CLEAN_ALL = $(addprefix clean-all-, $(ARCHS)) -NTHREADS=$(shell sysctl -n hw.ncpu) +.PHONY: all $(BUILDS) $(DEPS) clean-pkg $(CLEAN_DEPS) $(CLEAN_ALL) clean-all -all: build +all: $(BUILDS) -deps: - make -C deps -j$(NTHREADS) +$(BUILDS): build-%: deps-% + ./build.sh $* -clean-deps: - make -C deps clean-all +$(DEPS): deps-%: + make -C deps DEPS_ARCH=$* -clean: +$(CLEAN_DEPS): clean-deps-%: + make -C deps clean-all DEPS_ARCH=$* + +clean-pkg: rm -rf pkg -clean-all: clean-deps clean +$(CLEAN_ALL): clean-all-%: clean-deps-% clean-pkg -build: deps - ./build.sh +clean-all: $(CLEAN_ALL) diff --git a/macOS/build.sh b/macOS/build.sh index bba2664fc..3c19bb923 100755 --- a/macOS/build.sh +++ b/macOS/build.sh @@ -20,9 +20,32 @@ set -ex ROOTDIR=$(pwd)/.. +## +## Set settings based on architecture +## +path_remove () { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | sed 's/:$//'`"; } +path_prepend () { path_remove $1 $2; export $1="$2:${!1}"; } +PKG_ARCH=$1 +if [[ $PKG_ARCH == arm64 ]]; then + BREWDIR=/opt/homebrew + # Make sure /opt/homebrew/bin is set first in PATH (as it might come last) + path_prepend PATH /opt/homebrew/bin + MATLAB_ARCH=maca64 +else + BREWDIR=/usr/local + # Remove /opt/homebrew/bin from PATH, so it does not intervene with the x86_64 compilations + path_remove PATH /opt/homebrew/bin + MATLAB_ARCH=maci64 + # On x86_64 we need to differentiate between older and newer MATLAB versions + MATLAB_PATH_OLD=/Applications/MATLAB_R2016b.app +fi +MATLAB_PATH_NEW=/Applications/"$PKG_ARCH"/MATLAB_R2023b.app + +# Append texbin to PATH to access latexmk and friends +path_prepend PATH /Library/TeX/texbin # Set dependency directory -LIB64="$ROOTDIR"/macOS/deps/lib64 +LIB64="$ROOTDIR"/macOS/deps/"$PKG_ARCH"/lib64 ## Hack for statically linking libquadmath, similar to the one used in ## deps/Makefile for several libraries (there is no -static-libquadmath flag, @@ -32,9 +55,10 @@ LIB64="$ROOTDIR"/macOS/deps/lib64 ## - the macOS linker is different from GNU ld and does not have the equivalent of -Bstatic/-Bdynamic ## - libgfortran.spec does not include --as-needed on macOS, hence it will link the library anyways ## Also, it does not seem possible to override libgfortran.spec with the --specs option. -GCC_VERSION=$(sed -En "/^c[[:space:]]*=/s/c[[:space:]]*=[[:space:]]*'gcc-([0-9]+)'/\1/p" "$ROOTDIR"/scripts/homebrew-native.ini) +GCC_VERSION=$(sed -n "s|c = '$(BREWDIR)/bin/gcc-\([0-9]*\)'|\1|p" "$ROOTDIR"/scripts/homebrew-native-$PKG_ARCH.ini) + QUADMATH_DIR=$(mktemp -d) -ln -s /usr/local/opt/gcc/lib/gcc/$GCC_VERSION/libquadmath.a $QUADMATH_DIR +ln -s $BREWDIR/opt/gcc/lib/gcc/$GCC_VERSION/libquadmath.a $QUADMATH_DIR ## ## Compile Dynare @@ -44,19 +68,21 @@ cd "$ROOTDIR" # NB: the addition of -Wl,-ld_classic is a workaround for https://github.com/mesonbuild/meson/issues/12282 (see also the native file) common_meson_opts=(-Dbuild_for=matlab -Dbuildtype=release -Dprefer_static=true -Dfortran_args="[ '-B', '$LIB64/Slicot/' ]" \ -Dc_link_args="[ '-Wl,-ld_classic', '-L$QUADMATH_DIR' ]" -Dcpp_link_args="[ '-Wl,-ld_classic', '-L$QUADMATH_DIR' ]" -Dfortran_link_args="[ '-Wl,-ld_classic', '-L$QUADMATH_DIR' ]" \ - --native-file scripts/homebrew-native.ini) + --native-file scripts/homebrew-native-$PKG_ARCH.ini) -# Build for MATLAB ⩾ R2018a -meson setup "${common_meson_opts[@]}" -Dmatlab_path=/Applications/x86_64/MATLAB_R2023b.app build-matlab -meson compile -v -C build-matlab +# Build for MATLAB ⩾ R2018a (x86_64) and MATLAB ⩾ R2023b (arm64) +arch -$PKG_ARCH meson setup "${common_meson_opts[@]}" -Dmatlab_path="$MATLAB_PATH_NEW" build-matlab --wipe +arch -$PKG_ARCH meson compile -v -C build-matlab -# Build for MATLAB < R2018a -meson setup "${common_meson_opts[@]}" -Dmatlab_path=/Applications/MATLAB_R2016b.app build-old-matlab -meson compile -v -C build-old-matlab +if [[ $PKG_ARCH == x86_64 ]]; then + # Build for MATLAB < R2018a + arch -$PKG_ARCH meson setup "${common_meson_opts[@]}" -Dmatlab_path="$MATLAB_PATH_OLD" build-old-matlab --wipe + arch -$PKG_ARCH meson compile -v -C build-old-matlab +fi # If not in CI, build the docs if [[ -z $CI ]]; then - meson compile -v -C build-matlab doc + arch -$PKG_ARCH meson compile -v -C build-matlab doc ln -s build-matlab build-doc fi @@ -86,16 +112,23 @@ else # Get the first component, truncate it to 5 characters, and add the date LOCATION=$(echo "$VERSION" | cut -f1 -d"-" | cut -c 1-5)-"$DATE" fi +# Add architecture to LOCATION and VERSION +VERSION="$VERSION"-"$PKG_ARCH" +LOCATION="$LOCATION"-"$PKG_ARCH" NAME=dynare-"$VERSION" PKGFILES="$ROOTDIR"/macOS/pkg/"$NAME" mkdir -p \ "$PKGFILES"/preprocessor \ - "$PKGFILES"/mex/matlab/maci64-8.3-9.3 \ - "$PKGFILES"/mex/matlab/maci64-9.4-23.2 \ "$PKGFILES"/doc \ "$PKGFILES"/scripts \ "$PKGFILES"/contrib/ms-sbvar/TZcode +if [[ $PKG_ARCH == x86_64 ]]; then + mkdir -p "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-8.3-9.3 \ + "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-9.4-23.2 +else + mkdir -p "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-23.2 +fi cp -p "$ROOTDIR"/NEWS.md "$PKGFILES" cp -p "$ROOTDIR"/COPYING "$PKGFILES" @@ -112,8 +145,12 @@ cp -p "$ROOTDIR"/build-matlab/preprocessor/src/dynare-preprocessor "$PKGFILES" mkdir -p "$PKGFILES"/matlab/preprocessor64 ln -sf ../../preprocessor/dynare-preprocessor "$PKGFILES"/matlab/preprocessor64/dynare_m -cp -L "$ROOTDIR"/build-matlab/*.mexmaci64 "$PKGFILES"/mex/matlab/maci64-9.4-23.2 -cp -L "$ROOTDIR"/build-old-matlab/*.mexmaci64 "$PKGFILES"/mex/matlab/maci64-8.3-9.3 +if [[ $PKG_ARCH == x86_64 ]]; then + cp -L "$ROOTDIR"/build-matlab/*.mex"$MATLAB_ARCH" "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-9.4-23.2 + cp -L "$ROOTDIR"/build-old-matlab/*.mex"$MATLAB_ARCH" "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-8.3-9.3 +else + cp -L "$ROOTDIR"/build-matlab/*.mex"$MATLAB_ARCH" "$PKGFILES"/mex/matlab/"$MATLAB_ARCH"-23.2 +fi cp -p "$ROOTDIR"/scripts/dynare.el "$PKGFILES"/scripts cp -pr "$ROOTDIR"/contrib/ms-sbvar/TZcode/MatlabFiles "$PKGFILES"/contrib/ms-sbvar/TZcode @@ -124,13 +161,13 @@ cp "$ROOTDIR"/build-doc/preprocessor/doc/*.pdf "$PKGFILES" cp -r "$ROOTDIR"/build-doc/dynare-manual.html "$PKGFILES"/doc mkdir -p "$PKGFILES"/matlab/modules/dseries/externals/x13/macOS/64 -cp -p "$ROOTDIR"/macOS/deps/lib64/x13as/x13as "$PKGFILES"/matlab/modules/dseries/externals/x13/macOS/64 +cp -p "$ROOTDIR"/macOS/deps/$PKG_ARCH/lib64/x13as/x13as "$PKGFILES"/matlab/modules/dseries/externals/x13/macOS/64 cd "$ROOTDIR"/macOS/pkg # Dynare option -pkgbuild --root "$PKGFILES" --identifier org.dynare."$VERSION" --version "$VERSION" --install-location /Applications/Dynare/"$LOCATION" "$NAME".pkg +arch -$PKG_ARCH pkgbuild --root "$PKGFILES" --identifier org.dynare."$VERSION" --version "$VERSION" --install-location /Applications/Dynare/"$LOCATION" "$NAME".pkg # Create distribution.xml by replacing variables in distribution_template.xml sed -e "s/VERSION_NO_SPACE/$VERSION/g" \ @@ -148,7 +185,7 @@ sed -e "s/GCC_VERSION/$GCC_VERSION/g" \ "$ROOTDIR"/macOS/conclusion_template.html > "$ROOTDIR"/macOS/conclusion.html # Create installer -productbuild --distribution distribution.xml --resources "$ROOTDIR"/macOS --package-path ./"$NAME".pkg "$NAME"-productbuild.pkg +arch -$PKG_ARCH productbuild --distribution distribution.xml --resources "$ROOTDIR"/macOS --package-path ./"$NAME".pkg "$NAME"-productbuild.pkg # Cleanup rm -f ./distribution.xml diff --git a/macOS/conclusion_template.html b/macOS/conclusion_template.html index 25aa2721a..ab0bd77da 100644 --- a/macOS/conclusion_template.html +++ b/macOS/conclusion_template.html @@ -39,7 +39,7 @@ For this, follow https://brew.sh to install Homebrew and then type the following into Terminal.app:

brew install gcc@GCC_VERSION -

If you already have installed gcc-GCC_VERSION, Dynare will automatically prefer it for use_dll if the binaries are in /usr/local/bin/gcc-GCC_VERSION. Otherwise, it will fall back to Clang in /usr/bin/gcc.

+

If you already have installed gcc-GCC_VERSION, Dynare will automatically prefer it for use_dll if the binaries are either in /opt/homebrew/bin/gcc-GCC_VERSION (arm64) or in /usr/local/bin/gcc-GCC_VERSION (x86_64). Otherwise, it will fall back to Clang in /usr/bin/gcc (for both arm64 and x86_64).

\ No newline at end of file diff --git a/macOS/deps/Makefile b/macOS/deps/Makefile index 799553c7f..6786c009d 100644 --- a/macOS/deps/Makefile +++ b/macOS/deps/Makefile @@ -17,11 +17,19 @@ include versions.mk -GCC_VERSION = $(shell sed -En "/^c[[:space:]]*=/s/c[[:space:]]*=[[:space:]]*'gcc-([0-9]+)'/\1/p" ../../scripts/homebrew-native.ini) +# settings for different architectures +DEPS_ARCH ?= x86_64 # use x86_64 by default + +BREWDIR := $(if $(filter arm64,$(DEPS_ARCH)),/opt/homebrew,/usr/local) + +GCC_VERSION = $(shell sed -n "s|c = '$(BREWDIR)/bin/gcc-\([0-9]*\)'|\1|p" ../../scripts/homebrew-native-$(DEPS_ARCH).ini) + ROOT_PATH = $(realpath .) WGET_OPTIONS := --no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error +NTHREADS=$(shell sysctl -n hw.perflevel0.physicalcpu) + .PHONY: all build build-slicot build-x13as \ clean-lib clean-libslicot clean-x13as-bin \ clean-src clean-slicot-src clean-x13as-src \ @@ -41,34 +49,34 @@ clean-tar: clean-slicot-tar clean-x13as-tar clean-all: clean-lib clean-src clean-tar # -# Slicot +# slicot # tarballs/slicot-$(SLICOT_VERSION).tar.gz: mkdir -p tarballs wget $(WGET_OPTIONS) -O $@ https://deb.debian.org/debian/pool/main/s/slicot/slicot_$(SLICOT_VERSION).orig.tar.gz -sources64/slicot-$(SLICOT_VERSION): tarballs/slicot-$(SLICOT_VERSION).tar.gz - rm -rf sources64/slicot-* +$(DEPS_ARCH)/sources64/slicot-$(SLICOT_VERSION): tarballs/slicot-$(SLICOT_VERSION).tar.gz + rm -rf $(DEPS_ARCH)/sources64/slicot-* mkdir -p $@ tar xf $< --directory $@ --strip-components=1 touch $@ -lib64/Slicot/libslicot64_pic.a: sources64/slicot-$(SLICOT_VERSION) - make -C $< FORTRAN=gfortran LOADER=gfortran SLICOTLIB=../libslicot64_pic.a OPTS="-O2 -g -fdefault-integer-8" lib +$(DEPS_ARCH)/lib64/slicot/libslicot64_pic.a: $(DEPS_ARCH)/sources64/slicot-$(SLICOT_VERSION) + make -C $< FORTRAN=$(BREWDIR)/bin/gfortran LOADER=$(BREWDIR)/bin/gfortran SLICOTLIB=../libslicot64_pic.a OPTS="-O2 -g -fdefault-integer-8" lib -j$(NTHREADS) strip -S $ - + diff --git a/scripts/homebrew-native-arm64.ini b/scripts/homebrew-native-arm64.ini new file mode 100644 index 000000000..342143b16 --- /dev/null +++ b/scripts/homebrew-native-arm64.ini @@ -0,0 +1,15 @@ +# Meson native file for compiling under Homebrew arm64 + +[binaries] +cpp = '/opt/homebrew/bin/g++-13' +c = '/opt/homebrew/bin/gcc-13' +flex = '/opt/homebrew/opt/flex/bin/flex' +bison = '/opt/homebrew/opt/bison/bin/bison' + +[built-in options] +cpp_args = [ '-I/opt/homebrew/include', '-B', '/opt/homebrew/lib' ] +# XCode 15 (on Ventura and Sonoma) has a linker issue, see https://github.com/mesonbuild/meson/issues/12282, workaround is to use ld_classic +cpp_link_args = [ '-Wl,-ld_classic' ] +c_link_args = [ '-Wl,-ld_classic' ] +fortran_link_args = [ '-Wl,-ld_classic' ] +#fortran_args = [ '-B', '/Users/sebastien/slicot' ] \ No newline at end of file diff --git a/scripts/homebrew-native.ini b/scripts/homebrew-native-x86_64.ini similarity index 81% rename from scripts/homebrew-native.ini rename to scripts/homebrew-native-x86_64.ini index 41efd280b..158b27887 100644 --- a/scripts/homebrew-native.ini +++ b/scripts/homebrew-native-x86_64.ini @@ -1,8 +1,8 @@ # Meson native file for compiling under Homebrew / x86_64 [binaries] -cpp = 'g++-13' -c = 'gcc-13' +cpp = '/usr/local/bin/g++-13' +c = '/usr/local/bin/gcc-13' flex = '/usr/local/opt/flex/bin/flex' bison = '/usr/local/opt/bison/bin/bison'