SHELL:=/bin/sh define help_text # All subdirs will be created under the sudirectory where this makefile lives, i.e., # ./freesurfer ./packages ./install # # ----- build from scratch starting with these steps ---- # # $$ make nuke <--- remove subdirs ./freesurfer ./packages ./install (the source/build, install trees) # - you will have to re-check out the annex if you run nuke # # $$ make fsco <--- checkout the freesurfer source tree here under ./freesurfer # $$ make pkg_download <--- get 3rd party packages and place here under ./packages # $$ make annexco <--- annex checkout of data files. While not required to compile freesurfer, the install pass # "make install" will fail w/o some annex files. Beware that annexco takes a while. # # ----- incrementaly update source and build with steps below ----- # # $$ make fsupdate <--- tell git to update the ./freesurfer source tree only if no merge is required # # $$ make config_print <--- print the cmake command to see the configured options before generating makefiles # config <--- generate all makefiles with options configured below, CentOS 6,7, Ubuntu 16,18, MacOS # config_min <--- generate makefiles for a minimal build, i.e., freeview and many mri* commands are not built # # $$ make clean <--- run the clean target in the cmake generated Makefiles # # $$ make build <--- run parellel build with -j8 under ./freesurfer (using cmake generated makefiles) # build_s <--- run serial build with -j1 (useful for debugging if errors harder to see in parallel make output) # build_k <--- run parallel build with -j8 and -k to continue if errors encountered (useful for debugging) # build_s_k <--- run serial build with -j1 and -k # # $$ make run_freeview <--- if the freeview binary was built, try to run it and load a volume file # # $$ make install <--- run the install pass creating distribution under ./install # install_s <--- same as _s above for build target # install_k <--- same as _k above for build target # install_s_k <--- same as _k_s above for build target # # $$ make test <--- run some individual command tests - requires a python rev 3 in PATH, e.g., anaconda python # # *** For more complete testing run a recon-all command, e.g., on subject bert data endef this_makefile:=$(firstword $(MAKEFILE_LIST)) this_makefile_abspath:=$(abspath $(dir $(firstword $(MAKEFILE_LIST)))) TOPDIR:=$(this_makefile_abspath) PKGS_URL:=http://surfer.nmr.mgh.harvard.edu/pub/data/fspackages/prebuilt # darwin or linux os:=$(shell uname -s | tr -s '[A-Z]' '[a-z]') os_type:=$(shell uname -v | tr -s '[A-Z]' '[a-z]') # LINUX ifeq ($(os),linux) # linux: Ubuntu or CentOS os_rhel:=none os_rhel_release:= none os_ubuntu_release:=none ifneq (,$(wildcard /etc/redhat-release)) # CentOS version os_rhel:=$(shell cat /etc/redhat-release) os_rhel_release:=$(shell cat /etc/redhat-release | sed 's;^.*release ;;' | awk '{print $$1}' | sed 's;\..*;;') else ifneq (,$(wildcard /etc/os-release)) # Ubuntu version os_ubuntu_release:=$(shell cat /etc/os-release | grep "^VERSION_ID" | sed 's;^.*=;;' | sed 's;\";;g' | sed 's;\..*;;') endif # assume permission to run sudo on linux system # SUDO_CMD:= SUDO_CMD:=sudo ifneq (,$(findstring ubuntu,$(os_type))) # UBUNTU # *** Not guaranteed to be a comprehensive list # sudo apt-get install build-essential # sudo apt-get install libgl1-mesa-dev freeglut3-dev mesa-common-dev # sudo apt-get install libblas-dev liblapack-dev # sudo apt-get install ocl-icd-opencl-dev # sudo apt-get install libxmu-dev libxi-dev # sudo apt-get install libopencv-dev # Ubuntu 16: sudo apt-get install gcc-4.9 g++-4.9 gfortran-4.9 # Ubuntu 18: sudo apt-get install gcc-4.8 g++-4.8 gfortran-4.8 # sudo apt-get install xorg xorg-dev libx11-dev # sudo apt-get install tcl tcl-dev tk tk-dev # sudo apt-get install qt5-default qtcreator # sudo apt-get install libqt5x11extras5-dev # sudo apt-get install git-annex DEVTOOL_BASE=/usr/bin BIN_BASE:=$(DEVTOOL_BASE) LIB_BASE:=/usr/lib EXTRA_UBUNTU_LINKER_FLAGS:= ifeq (18,$(os_ubuntu_release)) # gcc-4.8 DEVTOOL_REV:=4.8 # tell linker not to ignore RPATH in binaries (needed as of Ubuntu 17+) EXTRA_UBUNTU_LINKER_FLAGS:=-Wl,--disable-new-dtags else ifeq (16,$(os_ubuntu_release)) # gcc-4.9 DEVTOOL_REV:=4.9 else # Will fail for now - FIX ME: need default DEVTOOL_REV:= endif CMAKE:=/usr/bin/cmake # CMAKE:=/usr/local/bin/cmake MAKE:=$(BIN_BASE)/make CC:=$(BIN_BASE)/gcc-$(DEVTOOL_REV) CXX:=$(BIN_BASE)/g++-$(DEVTOOL_REV) GFORTRAN_LIB_BASE:=$(LIB_BASE)/gcc/x86_64-linux-gnu GFORTRAN_LIBS:=$(GFORTRAN_LIB_BASE)/$(DEVTOOL_REV) F77:=$(BIN_BASE)/gfortran-$(DEVTOOL_REV) PKGS_ARCH:=centos7-packages.tar.gz qt_base:=$(LIB_BASE)/x86_64-linux-gnu/qt5 # else ifneq (,$(findstring CentOS,$(os_rhel))) else # end Ubuntu # Start with CentOS settings as default for all other linux systems # CENTOS # *** Not guaranteed to be a comprehensive list # sudo yum install qt-create qt-config.x86_64 # sudo yum install qt5-qtx11extras.x86_64 qt5-qtx11extras-devel.x86_64 # sudo yum install boost.x86_64 boost-devel.x86_64 # sudo yum install tk-devel.x86_64 # sudo yum install opencl-filesystem.noarch opencl-headers.noarch # sudo yum install opencv.x86_64 opencv-devel.x86_64 # CentOS 6: use scl enable devtoolset-2 bash to get gcc4.8 when running the build target # centOS 7: sudo yum install cmake3.x86_64 cmake3-data.noarch cmake3-doc.noarch cmake3-gui.x86_64 # yum install git-annex DEVTOOL_BASE=/usr/bin BIN_BASE:=$(DEVTOOL_BASE) LIB_BASE:=/usr/lib DEVTOOL_REV:=4.8.2 ifeq (6,$(os_rhel_release)) CMAKE:=/usr/pubsw/bin/cmake else CMAKE:=$(BIN_BASE)/cmake3 endif MAKE:=$(BIN_BASE)/make CC:=$(shell which gcc) CXX:=$(shell which g++) F77:=$(shell which gfortran) ifeq (6,$(os_rhel_release)) GFORTRAN_LIBS:=/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/$(DEVTOOL_REV) else GFORTRAN_LIBS:=$(LIB_BASE)/gcc/x86_64-redhat-linux/$(DEVTOOL_REV) endif PKGS_ARCH:=centos7-packages.tar.gz qt_base:=/usr/lib64 endif # CentOS # DARWIN (MAC) # # Homebrew requires a full install of Xcode (not just the command line tools). You can get the # most recent version fo Xcode from the App Store. For older versions of MacOS, you can get # a matching older version of Xcode from the Apple Developers web site (you will need an account # there), https://developer.apple.com/ # # In addition to installing homebrew (by default under /usr/local), install the gcc-5 compilers # # brew update # brew install gcc@5 else ifeq ($(os),darwin) # assume permission to run sudo on Mac SUDO_CMD:=sudo # SUDO_CMD:= # use homebrew HOMEBREW_ROOT:=/usr/local HOMEBREW_BIN_BASE:=$(HOMEBREW_ROOT)/bin HOMEBREW_CELLAR_BASE:=$(HOMEBREW_ROOT)/Cellar HOMEBREW_OPT_BASE:=$(HOMEBREW_ROOT)/opt CMAKE:=$(HOMEBREW_BIN_BASE)/cmake BIN_NO_CCACHE_BASE:=$(HOMEBREW_BIN_BASE) BIN_CCACHE_BASE:=$(HOMEBREW_OPT_BASE)/ccache/libexec # no ccache version of F77 F77:=$(BIN_NO_CCACHE_BASE)/gfortran-5 ifneq (,$(USE_CCACHE)) BIN_BASE:=$(BIN_CCACHE_BASE) $(warning +++ USING CCACHE versions of gcc and g++) else BIN_BASE:=$(BIN_NO_CCACHE_BASE) endif CC:=$(BIN_BASE)/gcc-5 CXX:=$(BIN_BASE)/g++-5 # GNU make 4.0 and above preserves correct order of log output with -jN for N>1 # brew install homebrew/core/make ifneq (,$(wildcard $(HOMEBREW_BIN_BASE)/gmake)) MAKE:=$(HOMEBREW_BIN_BASE)/gmake else # default should be make 3.8x MAKE:=/usr/bin/make endif PKGS_ARCH:=osx10.11-packages.tar.gz # qt_base=/Volumes/hd-3/Qt5.10.0/5.10.0/clang_64 qt_base=$(HOMEBREW_CELLAR_BASE)/qt/5.11.2 endif # darwin GIT_BASE:=$(TOPDIR) EXTRA_PKGS_BASE:=$(GIT_BASE)/packages BUILD_BASE:=$(GIT_BASE)/freesurfer INSTALL_BASE:=$(TOPDIR)/install # first or default target is help .PHONY: help nuke fsco pkg_download annexco fsupdate help: $(call help_text) # For complete checkout and build from scratch run targets: # nuke, fsco, pkg_download, annexco, config, build, install # Everything will be created underneath the parent subdir where this makefile fragment is located all_src: nuke fsco pkg_download annexco fsupdate nuke: mkdir -p $(GIT_BASE) (cd $(GIT_BASE) && $(SUDO_CMD) rm -rf ./freesurfer) fsco: mkdir -p $(GIT_BASE) (cd $(GIT_BASE) && git clone -b dev https://github.com/freesurfer/freesurfer.git) .PHONY: pkg_download pkg_download: (cd $(GIT_BASE) && mkdir -p ./packages && chmod -R 777 ./packages) (cd $(GIT_BASE) && rm -rf ./packages) (cd $(GIT_BASE) && curl -O $(PKGS_URL)/$(PKGS_ARCH)) (cd $(GIT_BASE) && tar zxpf $(PKGS_ARCH)) ls ./packages # Try to speed up with number of jobs for git annex get > 1 ifeq ($(os),darwin) # ANNEX_JOBS:=--jobs=10 ANNEX_JOBS:= else # option not available on linux ANNEX_JOBS:= endif annexco: (cd $(BUILD_BASE) && git remote add datasrc http://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/repo/annex.git) (cd $(BUILD_BASE) && git fetch datasrc) (cd $(BUILD_BASE) && git annex get $(ANNEX_JOBS) .) (cd $(BUILD_BASE) && git status) # ignore this error, but check for broken soft links which means annex fetch had a problem -(cd $(BUILD_BASE) && find . | xargs file | grep -i "broken") # only update source if can fast forward (no merge required) fsupdate: (cd $(BUILD_BASE) && git pull --ff-only) ifndef config_cmd ifeq ($(os),linux) ifneq (,$(findstring ubuntu,$(os_type))) # Ubuntu config_cmd:=\ CC=$(CC) \ CXX=$(CXX) \ FC=$(F77) \ $(CMAKE) \ -DCMAKE_MAKE_PROGRAM=$(MAKE) \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DFS_PACKAGES_DIR=$(EXTRA_PKGS_BASE) \ -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS} -I/usr/include/tcl -Wno-deprecated -Wno-deprecated-declarations" \ -DX11_INCLUDE_DIR=/usr/include/X11 \ -DOPENGL_glu_LIBRARY=$(LIB_BASE)/x86_64-linux-gnu/libGLU.so.1 \ -DOpenCL_INCLUDE_DIRS=/usr/include \ -DCMAKE_RULE_MESSAGES:BOOL=ON \ -DCMAKE_INSTALL_PREFIX="$(INSTALL_BASE)" \ -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} $(EXTRA_UBUNTU_LINKER_FLAGS) -L$(LIB_BASE)/x86_64-linux-gnu -L/usr/local/lib -lz" \ -DGFORTRAN_LIBRARIES=$(GFORTRAN_LIBS)/libgfortran.so # else ifneq (,$(findstring CentOS,$(os_rhel))) else # end Ubuntu # Start with CentOS settings as default for all other linux systems config_cmd:=\ $(CMAKE) \ -DCMAKE_MAKE_PROGRAM=$(MAKE) \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DFS_PACKAGES_DIR=$(EXTRA_PKGS_BASE) \ -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-deprecated-declarations" \ -DCMAKE_RULE_MESSAGES:BOOL=ON \ -DCMAKE_INSTALL_PREFIX="$(INSTALL_BASE)" \ -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -lz" \ -DGFORTRAN_LIBRARIES=$(GFORTRAN_LIBS)/libgfortran.so endif # CentOS/default linux else ifeq ($(os),darwin) config_cmd=\ CC=$(CC) \ CXX=$(CXX) \ FC=$(F77) \ $(CMAKE) \ -DCMAKE_MAKE_PROGRAM=$(MAKE) \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DFS_PACKAGES_DIR=$(EXTRA_PKGS_BASE) \ -DCMAKE_RULE_MESSAGES:BOOL=ON \ -DCMAKE_INSTALL_PREFIX="$(INSTALL_BASE)" endif # darwin endif # config_cmd # Do minimal build for target config_min ifeq (config_min,$(findstring config_min,$(MAKECMDGOALS))) config_cmd+=-DMINIMAL:BOOL=ON endif ifneq (,$(wildcard $(qt_base))) config_cmd+=-DCMAKE_PREFIX_PATH=$(qt_base) else $(warning Could not stat path to qt distribution $(qt_base), so skipping adding it via -DCMAKE_PREFIX_PATH) endif export config_cmd .PHONY: config_print config config_min config_common clean config_print: @echo "$(config_cmd)" # Allow devtoolsets (with different compilers) to be used for CentOS builds devtoolset_config_cmd= config config_min: ifeq (6,$(os_rhel_release)) scl enable devtoolset-2 '$(MAKE) config_cmd=$(config_cmd) -f $(this_makefile) config_common' else $(MAKE) -f $(this_makefile) config_common endif config_common: (cd $(BUILD_BASE) && rm -f CMakeCache.txt && rm -f cmake.log) (cd $(BUILD_BASE) && $(config_cmd) . 2>&1 | tee -a cmake.log) ifndef MAKE_OPTS MAKE_OPTS:=VERBOSE=1 define make_opt_keepgoing MAKE_OPTS+=-k endef define make_opt_serial MAKE_OPTS+=-j1 endef define make_opt_parallel MAKE_OPTS+=-j8 endef endif # MAKE_OPTS export MAKE_OPTS clean: (cd $(BUILD_BASE) && $(MAKE) $(MAKE_OPT) clean) # target "build" default is to build with VERBOSE and -j8 # target "build_k" or append _k to target for -k keepgoing option past any compilation errors # target "build_s" or append _s to build serially (-j1) which is useful for debugging builds especially # target "build_k_s" to combine options -k and -j1 # default is to build parallel with -j8 .PHONY: build build_k build_s build_k_s build_s_k build build_k build_s build_k_s build_s_k: $(if $(findstring _s,$@),$(eval $(make_opt_serial)),$(eval $(make_opt_parallel))) $(if $(findstring _k,$@),$(eval $(make_opt_keepgoing)),) ifeq (6,$(os_rhel_release)) scl enable devtoolset-2 '$(MAKE) -f $(this_makefile) build_common' else # assume native compilers should work $(MAKE) $(MAKE_OPTS) -f $(this_makefile) build_common endif .PHONY: build_common # build target above runs common build target build_common: which $(MAKE) && $(MAKE) --version (cd $(BUILD_BASE) && rm -f make.log && $(MAKE) $(MAKE_OPTS) 2>&1 | tee -a make.log) # default is to build parallel with -j8 .PHONY: install install_k install_s install_k_s install_s_k # Assume nothing left to be compiled when install target is run, so scl enable does not need to be run install install_k install_s install_k_s install_s_k: $(if $(findstring _s,$@),$(eval $(make_opt_serial)),$(eval $(make_opt_parallel))) $(if $(findstring _k,$@),$(eval $(make_opt_keepgoing)),) mkdir -p $(INSTALL_BASE) (cd $(INSTALL_BASE) && $(SUDO_CMD) rm -rf *) (cd $(BUILD_BASE) && rm -f install.log && $(SUDO_CMD) $(MAKE) $(MAKE_OPTS) install 2>&1 | tee -a install.log) ls $(INSTALL_BASE) .PHONY: test python_rev:=$(shell python --version) # uncomment and add the path to your license here # test: export FS_LICENSE= test: export FREESURFER_HOME=$(INSTALL_BASE) test: export CTEST_OUTPUT_ON_FAILURE=1 test: ifeq (,$(findstring Python 3,$(python_rev))) @echo "Cannot run $@ target without a python version 3.X in PATH" else (cd $(BUILD_BASE) && rm -f test.log && $(MAKE) $(MAKE_OPT) test 2>&1 | tee -a test.log) endif # After install target, check if GUI based freeview runs. # Note that freeview is not built in a "minimal" buid with -DMININAL cmake option freeview_volume:=$(INSTALL_BASE)/subjects/cvs_avg35/mri/T1.mgz ifeq (,$(wildcard $(freeview_volume))) freeview_volume:= endif ifeq ($(os),linux) freeview_binary:=freeview freeview_cmd:=./$(freeview_binary) $(freeview_volume) freeview_install_dir:=$(INSTALL_BASE)/bin else ifeq ($(os),darwin) freeview_binary:=Freeview.app freeview_cmd:=open -a $(freeview_binary) $(freeview_volume) freeview_install_dir:=$(INSTALL_BASE) endif .PHONY: run_freeview run_freeview: ifneq (,$(wildcard $(BUILD_BASE)/freeview/$(freeview_binary))) (cd $(BUILD_BASE)/freeview && $(freeview_cmd)) else ifneq (,$(wildcard $(freeview_install_dir)/$(freeview_binary))) (cd $(freeview_install_dir) && $(freeview_cmd)) else $(warning No freeview binary to run under $(BUILD_BASE)/freeview or $(INSTALL_BASE)) $(warning Please check that freeview was built ad/or installed) endif # test for freeview