diff options
-rw-r--r-- | CMakeLists.txt | 20 | ||||
-rw-r--r-- | caffe2/CMakeLists.txt | 51 | ||||
-rw-r--r-- | cmake/Summary.cmake | 2 | ||||
-rw-r--r-- | setup.py | 36 | ||||
-rwxr-xr-x | tools/build_pytorch_libs.sh | 36 | ||||
-rw-r--r-- | torch/CMakeLists.txt | 10 |
6 files changed, 119 insertions, 36 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index aa943e4378..b87cb3686e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,20 +30,23 @@ if(NOT DEFINED BLAS_SET_BY_USER) set(BLAS_SET_BY_USER ${BLAS_SET_BY_USER} CACHE STRING "Marks whether BLAS was manually set by user or auto-detected") endif() -# These lines are an attempt to make find_package(cuda) pick up -# libcuda.dylib, and not cuda.framework. It doesn't work all -# the time, but it seems to help for some users. -# TODO: replace this with a more robust fix +# Apple specific if(APPLE) + # These lines are an attempt to make find_package(cuda) pick up + # libcuda.dylib, and not cuda.framework. It doesn't work all + # the time, but it seems to help for some users. + # TODO: replace this with a more robust fix set(CMAKE_FIND_FRAMEWORK LAST) set(CMAKE_FIND_APPBUNDLE LAST) -endif() -# Get clang version on macOS -if(APPLE) + # Get clang version on macOS EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string ) string(REGEX REPLACE "Apple LLVM version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string}) MESSAGE( STATUS "CLANG_VERSION_STRING: " ${CLANG_VERSION_STRING} ) + + + # RPATH stuff + set(CMAKE_MACOSX_RPATH ON) endif() # ---[ Options. @@ -138,6 +141,9 @@ cmake_dependent_option( option(USE_DISTRIBUTED "Use THD (distributed)" OFF) option(USE_DISTRIBUTED_MW "Use THD (distributed) master worker" OFF) +# Used when building Caffe2 through setup.py +option(BUILDING_WITH_TORCH_LIBS "Tell cmake if Caffe2 is being built alongside torch libs" OFF) + if (USE_ATEN) set(BUILD_ATEN ${USE_ATEN}) endif() diff --git a/caffe2/CMakeLists.txt b/caffe2/CMakeLists.txt index 250fb3005d..0c69af7c52 100644 --- a/caffe2/CMakeLists.txt +++ b/caffe2/CMakeLists.txt @@ -367,11 +367,12 @@ if(BUILD_CAFFE2) if (BUILD_PYTHON) # Python site-packages # Get canonical directory for python site packages (relative to install - # location). It varys from system to system. + # location). It varies from system to system. pycmd(PYTHON_SITE_PACKAGES " from distutils import sysconfig print(sysconfig.get_python_lib(prefix='')) ") + SET(PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES} PARENT_SCOPE) # for Summary # ---[ Options. SET(PYTHON_LIB_REL_PATH "${PYTHON_SITE_PACKAGES}" CACHE STRING "Python installation path (relative to CMake installation prefix)") message(STATUS "Using ${PYTHON_LIB_REL_PATH} as python relative installation path") @@ -391,6 +392,26 @@ if(BUILD_CAFFE2) endif() endif() + # Allow different install locations for libcaffe2 + # For setuptools installs (that all build Python), install libcaffe2 into + # site-packages, alongside the torch libraries. The pybind11 library needs + # an rpath to the torch library folder + # For cmake installs, including c++ only installs, install libcaffe2 into + # CMAKE_INSTALL_PREFIX/lib . The pybind11 library can have a hardcoded + # rpath + if(APPLE) + set(_rpath_portable_origin "@loader_path") + else() + set(_rpath_portable_origin $ORIGIN) + endif(APPLE) + set(caffe2_pybind11_rpath "${_rpath_portable_origin}") + if(${BUILDING_WITH_TORCH_LIBS}) + # site-packages/caffe2/python/caffe2_pybind11_state + # site-packages/torch/lib + set(caffe2_pybind11_rpath "${_rpath_portable_origin}/../../torch/lib") + endif(${BUILDING_WITH_TORCH_LIBS}) + + # ---[ Python. add_library(caffe2_pybind11_state MODULE ${Caffe2_CPU_PYTHON_SRCS}) set_target_properties(caffe2_pybind11_state PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") @@ -399,15 +420,19 @@ if(BUILD_CAFFE2) if (APPLE) set_target_properties(caffe2_pybind11_state PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") endif() - set_target_properties( - caffe2_pybind11_state PROPERTIES LIBRARY_OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/caffe2/python) target_link_libraries( caffe2_pybind11_state caffe2_library) if (WIN32) target_link_libraries(caffe2_pybind11_state ${PYTHON_LIBRARIES}) endif(WIN32) + + # Install caffe2_pybind11_state(_gpu|hip) in site-packages/caffe2/python, + # so it needs an rpath to find libcaffe2 + set_target_properties( + caffe2_pybind11_state PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/caffe2/python) install(TARGETS caffe2_pybind11_state DESTINATION "${PYTHON_LIB_REL_PATH}/caffe2/python") + set_target_properties(caffe2_pybind11_state PROPERTIES INSTALL_RPATH "${caffe2_pybind11_rpath}") if(USE_CUDA) add_library(caffe2_pybind11_state_gpu MODULE ${Caffe2_GPU_PYTHON_SRCS}) @@ -417,15 +442,18 @@ if(BUILD_CAFFE2) if (APPLE) set_target_properties(caffe2_pybind11_state_gpu PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") endif() - set_target_properties( - caffe2_pybind11_state_gpu PROPERTIES LIBRARY_OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/caffe2/python) target_link_libraries( caffe2_pybind11_state_gpu caffe2_library caffe2_gpu_library) if (WIN32) target_link_libraries(caffe2_pybind11_state_gpu ${PYTHON_LIBRARIES}) endif(WIN32) + + # Install with same rpath as non-gpu caffe2_pybind11_state + set_target_properties( + caffe2_pybind11_state_gpu PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/caffe2/python) install(TARGETS caffe2_pybind11_state_gpu DESTINATION "${PYTHON_LIB_REL_PATH}/caffe2/python") + set_target_properties(caffe2_pybind11_state_gpu PROPERTIES INSTALL_RPATH "${caffe2_pybind11_rpath}") endif() if(USE_ROCM) @@ -436,15 +464,18 @@ if(BUILD_CAFFE2) if (APPLE) set_target_properties(caffe2_pybind11_state_hip PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") endif() - set_target_properties( - caffe2_pybind11_state_hip PROPERTIES LIBRARY_OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/caffe2/python) target_link_libraries( caffe2_pybind11_state_hip caffe2_library caffe2_hip_library) if (WIN32) target_link_libraries(caffe2_pybind11_state_hip ${PYTHON_LIBRARIES}) endif(WIN32) + + # Install with same rpath as non-hip caffe2_pybind11_state + set_target_properties( + caffe2_pybind11_state_hip PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/caffe2/python) install(TARGETS caffe2_pybind11_state_hip DESTINATION "${PYTHON_LIB_REL_PATH}/caffe2/python") + set_target_properties(caffe2_pybind11_state_hip PROPERTIES INSTALL_RPATH "${caffe2_pybind11_rpath}") endif() if (MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio") diff --git a/cmake/Summary.cmake b/cmake/Summary.cmake index ef682119db..8151f9c9ae 100644 --- a/cmake/Summary.cmake +++ b/cmake/Summary.cmake @@ -35,7 +35,9 @@ function (caffe2_print_configuration_summary) message(STATUS " BUILD_PYTHON : ${BUILD_PYTHON}") if (${BUILD_PYTHON}) message(STATUS " Python version : ${PYTHONLIBS_VERSION_STRING}") + message(STATUS " Python executable : ${PYTHON_EXECUTABLE}") message(STATUS " Python includes : ${PYTHON_INCLUDE_DIR}") + message(STATUS " Python site-packages: ${PYTHON_SITE_PACKAGES}") endif() message(STATUS " BUILD_SHARED_LIBS : ${BUILD_SHARED_LIBS}") message(STATUS " BUILD_TEST : ${BUILD_TEST}") @@ -86,7 +86,6 @@ # LD_LIBRARY_PATH # we will search for libraries in these paths - from setuptools import setup, Extension, distutils, Command, find_packages import setuptools.command.build_ext import setuptools.command.install @@ -176,6 +175,8 @@ cwd = os.path.dirname(os.path.abspath(__file__)) lib_path = os.path.join(cwd, "torch", "lib") third_party_path = os.path.join(cwd, "third_party") tmp_install_path = lib_path + "/tmp_install" +rel_site_packages = distutils.sysconfig.get_python_lib(prefix='') +full_site_packages = distutils.sysconfig.get_python_lib() class PytorchCommand(setuptools.Command): @@ -302,6 +303,7 @@ def build_libs(libs): build_libs_cmd = ['bash', 'tools/build_pytorch_libs.sh'] my_env = os.environ.copy() my_env["PYTORCH_PYTHON"] = sys.executable + my_env["CMAKE_PREFIX_PATH"]=full_site_packages my_env["NUM_JOBS"] = str(NUM_JOBS) my_env["ONNX_NAMESPACE"] = ONNX_NAMESPACE if not IS_WINDOWS: @@ -333,7 +335,6 @@ def build_libs(libs): build_libs_cmd += ['--use-gloo-ibverbs'] if USE_DISTRIBUTED_MW: build_libs_cmd += ['--use-distributed-mw'] - if FULL_CAFFE2: build_libs_cmd += ['--full-caffe2'] @@ -474,7 +475,6 @@ build_ext_parent = ninja_build_ext if USE_NINJA \ class build_ext(build_ext_parent): def run(self): - # Print build options if USE_NUMPY: print('-- Building with NumPy bindings') @@ -533,26 +533,29 @@ class build_ext(build_ext_parent): self.copy_file(export_lib, target_lib) def build_extensions(self): - # If also building Caffe2 python, then we need this extra logic copied - # from the old setup_caffe2.py + # The caffe2 extensions are created in + # tmp_install/lib/pythonM.m/site-packages/caffe2/python/ + # and need to be copied to build/lib.linux.... , which will be a + # platform dependent build folder created by the "build" command of + # setuptools. Only the contents of this folder are installed in the + # "install" command by default. if FULL_CAFFE2: - pybind_exts = [ + # We only make this copy for Caffe2's pybind extensions + caffe2_pybind_exts = [ 'caffe2.python.caffe2_pybind11_state', 'caffe2.python.caffe2_pybind11_state_gpu', + 'caffe2.python.caffe2_pybind11_state_hip', ] - # The cmake of Caffe2 puts these in the site-packages rather than - # the build directory like the other torch extensions - sp_dir = distutils.sysconfig.get_python_lib(prefix='') i = 0 while i < len(self.extensions): ext = self.extensions[i] - if ext.name not in pybind_exts: + if ext.name not in caffe2_pybind_exts: i += 1 continue fullname = self.get_ext_fullname(ext.name) filename = self.get_ext_filename(fullname) - src = os.path.join(tmp_install_path, sp_dir, filename) + src = os.path.join(tmp_install_path, rel_site_packages, filename) if not os.path.exists(src): print("{} does not exist".format(src)) del self.extensions[i] @@ -565,6 +568,12 @@ class build_ext(build_ext_parent): i += 1 distutils.command.build_ext.build_ext.build_extensions(self) + def get_outputs(self): + outputs = distutils.command.build_ext.build_ext.get_outputs(self) + if FULL_CAFFE2: + outputs += [os.path.join(self.build_lib, d) for d in ['caffe', 'caffe2']] + return outputs + class build(distutils.command.build.build): sub_commands = [ @@ -963,7 +972,10 @@ def make_relative_rpath(path): ################################################################################ extensions = [] -packages = find_packages(exclude=('tools', 'tools.*', 'caffe2', 'caffe2.*', 'caffe', 'caffe.*')) +if FULL_CAFFE2: + packages = find_packages(exclude=('tools', 'tools.*')) +else: + packages = find_packages(exclude=('tools', 'tools.*', 'caffe2', 'caffe2.*', 'caffe', 'caffe.*')) C = Extension("torch._C", libraries=main_libraries, sources=main_sources, diff --git a/tools/build_pytorch_libs.sh b/tools/build_pytorch_libs.sh index b385d24e27..e3d6202c69 100755 --- a/tools/build_pytorch_libs.sh +++ b/tools/build_pytorch_libs.sh @@ -68,6 +68,13 @@ if [[ -n "$CPPFLAGS" ]]; then USER_LDFLAGS="$USER_LDFLAGS $CPPFLAGS" fi +# Use ccache if available (this path is where Homebrew installs ccache symlinks) +if [ "$(uname)" == 'Darwin' ]; then + if [ -d '/usr/local/opt/ccache/libexec' ]; then + CCACHE_WRAPPER_PATH=/usr/local/opt/ccache/libexec + fi +fi + cd "$(dirname "$0")/.." PWD=`printf "%q\n" "$(pwd)"` BASE_DIR="$PWD" @@ -182,8 +189,7 @@ function build() { ${CMAKE_INSTALL} -j"$NUM_JOBS" popd - local lib_prefix=$INSTALL_DIR/lib/lib$1 - + # Fix rpaths of shared libraries if [[ $(uname) == 'Darwin' ]]; then pushd "$INSTALL_DIR/lib" for lib in *.dylib; do @@ -231,10 +237,22 @@ function build_nccl() { # detected them (to ensure that we have a consistent view between the # PyTorch and Caffe2 builds.) function build_caffe2() { + if [[ -z $EXTRA_CAFFE2_CMAKE_FLAGS ]]; then + EXTRA_CAFFE2_CMAKE_FLAGS=() + fi + if [[ -n $CCACHE_WRAPPER_PATH ]]; then + EXTRA_CAFFE2_CMAKE_FLAGS+=("-DCMAKE_C_COMPILER=$CCACHE_WRAPPER_PATH/gcc") + EXTRA_CAFFE2_CMAKE_FLAGS+=("-DCMAKE_CXX_COMPILER=$CCACHE_WRAPPER_PATH/g++") + fi + if [[ -n $CMAKE_PREFIX_PATH ]]; then + EXTRA_CAFFE2_CMAKE_FLAGS+=("-DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH") + fi + mkdir -p build pushd build ${CMAKE_VERSION} .. \ ${CMAKE_GENERATOR} \ + -DBUILDING_WITH_TORCH_LIBS=ON \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DBUILD_CAFFE2=$FULL_CAFFE2 \ -DBUILD_ATEN=ON \ @@ -256,8 +274,8 @@ function build_caffe2() { -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ -DCMAKE_C_FLAGS="$USER_CFLAGS" \ -DCMAKE_CXX_FLAGS="$USER_CFLAGS" \ - -DCMAKE_EXE_LINKER_FLAGS="$USER_LDFLAGS" \ - -DCMAKE_SHARED_LINKER_FLAGS="$USER_LDFLAGS" + -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS $USER_LDFLAGS" \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS $USER_LDFLAGS" ${EXTRA_CAFFE2_CMAKE_FLAGS[@]} # STOP!!! Are you trying to add a C or CXX flag? Add it # to CMakeLists.txt and aten/CMakeLists.txt, not here. # We need the vanilla cmake build to work. @@ -274,6 +292,16 @@ function build_caffe2() { done fi popd + + # Fix rpaths of shared libraries + if [[ $(uname) == 'Darwin' ]]; then + pushd "$INSTALL_DIR/lib" + for lib in *.dylib; do + echo "Updating install_name for $lib" + install_name_tool -id @rpath/$lib $lib + done + popd + fi } # In the torch/lib directory, create an installation directory diff --git a/torch/CMakeLists.txt b/torch/CMakeLists.txt index 204efaee9b..7a486aba09 100644 --- a/torch/CMakeLists.txt +++ b/torch/CMakeLists.txt @@ -116,14 +116,18 @@ endif() if(APPLE) set(CMAKE_MACOSX_RPATH ON) endif() +# Use separate rpaths during build and install phases set(CMAKE_SKIP_BUILD_RPATH FALSE) +# Don't use the install-rpath during the build phase set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) +# Automatically add all linked folders that are NOT in the build directory to +# the rpath (per library?) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +# Always ensure that CMAKE_INSTALL_PREFIX/lib is in the rpath list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) if("${isSystemDir}" STREQUAL "-1") - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif() |