Attachment 'makefile.txt'

Download

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

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.