diff --git a/BUILDING.md b/BUILDING.md
index 6c1aea4619..6fade1852a 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -2,11 +2,11 @@ Advanced Build Configuration
============================
## Table of Contents
-- [Optional Components](#Optional-Components)
-- [Third Party Plugins](#Plugins)
-- [Other Build Options](#Other-Build-Options)
-- [USD Developer Options](#USD-Developer-Options)
-- [Optimization Options](#Optimization-Options)
+- [Optional Components](#optional-components)
+- [Third Party Plugins](#third-party-plugins)
+- [Other Build Options](#other-build-options)
+- [USD Developer Options](#usd-developer-options)
+- [Optimization Options](#optimization-options)
## Optional Components
@@ -19,7 +19,7 @@ removes the need for their dependencies when building USD.
This component contains Hydra, a high-performance graphics rendering engine.
Disable this component by specifying the cmake flag ```PXR_BUILD_IMAGING=FALSE``` when
-invoking cmake. Disabling this component will also disable the [USD Imaging](#USD-Imaging)
+invoking cmake. Disabling this component will also disable the [USD Imaging](#usd-imaging)
component.
##### USD Imaging
@@ -28,10 +28,10 @@ This component provides the USD imaging delegates for Hydra, as well as
usdview, a standalone native viewer for USD files.
Disable this component by specifying the cmake flag ```PXR_BUILD_USD_IMAGING=FALSE``` when
-invoking cmake. Enabling this component will enable the [Imaging](#Imaging)
+invoking cmake. Enabling this component will enable the [Imaging](#imaging)
component.
-## Plugins
+## Third Party Plugins
USD provides several plugins for integration with third-party software packages,
including Maya, Katana, and Alembic. There is additional documentation on each plugin
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c3c97ddcc1..46fa62493b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,10 @@ include(CXXDefaults)
add_definitions(${_PXR_CXX_DEFINITIONS})
set(CMAKE_CXX_FLAGS ${_PXR_CXX_FLAGS})
+if(POLICY CMP0020)
+ cmake_policy(SET CMP0020 OLD)
+endif()
+
include(Public)
add_subdirectory(pxr)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..5e235ae2ec
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,2 @@
+Thank you for your interest in contributing to USD! We ask that
+potential contributors review our guidelines on [contributing](http://openusd.org/docs/Contributing-to-USD.html) before submitting a pull request.
diff --git a/ISSUES.md b/ISSUES.md
deleted file mode 100644
index c475e9e41b..0000000000
--- a/ISSUES.md
+++ /dev/null
@@ -1,50 +0,0 @@
-Filing Issues for USD
-=====================
-
-We are very excited to gather community feedback for USD. If you have found an
-issue, we ask that you follow these guidelines when filing.
-
-- List all relevant configuration information, including operating system,
-software versions, hardware configuration, driver versions etc.
-
-- Provide a "Minimal Repro", meaning the smallest set of steps necessary to
-reproduce the bug.
-
-Below is an example bug description:
-
- *Title*: Usd Stage Fails to Save.
-
- *Content*:
- System Information:
- ```
- Operating System: Ubuntu 12.04 64Bit
- Hardware Configuration: Intel Core i5, Nvidia GTX 980(Driver 343.22)
- Intel TBB Version: 4.4 Update 5
- G++ Version: 6.1.0
- Python Version: 2.7.5
- Boost Version: 1.6.1
- OpenSubdiv Version: 3.0.5
- GLEW Version: 1.10.0
- OpenImageIO Version: 1.5.11
- Ptex Version: 2.0.30
- Qt Version: 4.8.1
- Pyside Version: 1.2.2
- ```
-
-
- Repro case:
- 1. Launch Python
- 2. Run the following snippet
-
- ```python
-
- >>> from pxr import Usd
- >>> stage = Usd.Stage.CreateNew('hello.usda')
- >>> stage.GetRootLayer().Save()
- ```
-
- 3. Note that 'hello.usda' is not created on disk, my expectation is that
- it would be
-
-These guidelines will help us get to issues more quickly, we appreciate your
-help!
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..9a194e3aa9
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,8 @@
+### System Information (OS, Hardware, etc.)
+
+### Package Versions
+
+### Build Flags
+
+### Steps to Reproduce
+1.
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..a9f1468813
--- /dev/null
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,9 @@
+### Description of Change(s)
+
+
+### Included Commit(s)
+-
+
+### Fixes Issue(s)
+-
+
diff --git a/README.md b/README.md
index f60a3078be..14b9260616 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ Getting Help
------------
Need help understanding certain concepts in USD? See
-[Getting Help with USD](http://openusd.org/docs/Getting-Help-With-USD.html).
+[Getting Help with USD](http://openusd.org/docs/Getting-Help-with-USD.html).
If you are experiencing undocumented problems with the software,
please read our [issue guidelines](ISSUES.md) and file a bug via the
diff --git a/cmake/defaults/CXXDefaults.cmake b/cmake/defaults/CXXDefaults.cmake
index f637fb71bc..8d711ac175 100644
--- a/cmake/defaults/CXXDefaults.cmake
+++ b/cmake/defaults/CXXDefaults.cmake
@@ -26,7 +26,7 @@ include(Version)
if (CMAKE_COMPILER_IS_GNUCXX)
include(gccdefaults)
-elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
include(clangdefaults)
elseif(MSVC)
include(msvcdefaults)
diff --git a/cmake/defaults/Options.cmake b/cmake/defaults/Options.cmake
index 5227408c86..eeeaca9f16 100644
--- a/cmake/defaults/Options.cmake
+++ b/cmake/defaults/Options.cmake
@@ -21,12 +21,14 @@
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
+option(PXR_STRICT_BUILD_MODE "Turn on additional warnings. Enforce all warnings as errors." OFF)
option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" ON)
option(PXR_BUILD_IMAGING "Build imaging components" ON)
option(PXR_BUILD_USD_IMAGING "Build USD imaging components" ON)
-option(PXR_BUILD_KATANA_PLUGIN "Build usd katana plugin" OFF)
-option(PXR_BUILD_MAYA_PLUGIN "Build usd maya plugin" OFF)
+option(PXR_BUILD_KATANA_PLUGIN "Build usd katana plugin" ON)
+option(PXR_BUILD_MAYA_PLUGIN "Build usd maya plugin" ON)
option(PXR_BUILD_ALEMBIC_PLUGIN "Build the Alembic plugin for USD" OFF)
+option(PXR_MAYA_TBB_BUG_WORKAROUND "Turn on linker flag (-Wl,-Bsymbolic) to work around a Maya TBB bug" OFF)
set(PXR_INSTALL_LOCATION ""
CACHE
diff --git a/cmake/defaults/Packages.cmake b/cmake/defaults/Packages.cmake
index 36532ca8e7..e947f966f7 100644
--- a/cmake/defaults/Packages.cmake
+++ b/cmake/defaults/Packages.cmake
@@ -30,10 +30,12 @@ find_package(PythonInterp 2.7 REQUIRED)
# --Boost
find_package(Boost
COMPONENTS
+ date_time
iostreams
python
regex
system
+ thread
program_options
REQUIRED
)
@@ -58,17 +60,27 @@ find_library(M_LIB m)
find_package(Jinja2)
if (NOT PXR_MALLOC_LIBRARY)
- message(STATUS "Using default system allocator because PXR_MALLOC_LIBRARY is unspecified")
+ if (NOT WIN32)
+ message(STATUS "Using default system allocator because PXR_MALLOC_LIBRARY is unspecified")
+ endif()
endif()
# Developer Options Package Requirements
# ----------------------------------------------
if (PXR_VALIDATE_GENERATED_CODE)
- find_package(BISON 2.4.1 EXACT)
+ if(WIN32)
+ find_package(BISON 2.7 EXACT)
+ else()
+ find_package(BISON 2.4.1 EXACT)
+ endif()
# Flex 2.5.39+ is required, generated API is generated incorrectly in
# 2.5.35, at least. scan_bytes generates with (..., int len, ...) instead of
# the correct (..., yy_size_t len, ...). Lower at your own peril.
- find_package(FLEX 2.5.39 EXACT)
+ if(WIN32)
+ find_package(FLEX 2.5.37 EXACT)
+ else()
+ find_package(FLEX 2.5.39 EXACT)
+ endif()
endif()
@@ -85,13 +97,17 @@ if (PXR_BUILD_IMAGING)
find_package(OpenSubdiv 3 REQUIRED)
# --Ptex
find_package(PTex REQUIRED)
- # --X11
- find_package(X11)
+ if(UNIX)
+ # --X11
+ find_package(X11)
+ endif()
# --Qt
find_package(Qt4)
if (QT4_FOUND)
- find_package(PySideTools REQUIRED)
+ find_package(PySide REQUIRED)
endif()
+ # --Zlib
+ find_package(ZLIB REQUIRED)
endif()
# Third Party Plugin Package Requirements
diff --git a/cmake/defaults/ProjectDefaults.cmake b/cmake/defaults/ProjectDefaults.cmake
index 5b3a4ff052..21aa51965b 100644
--- a/cmake/defaults/ProjectDefaults.cmake
+++ b/cmake/defaults/ProjectDefaults.cmake
@@ -55,4 +55,4 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
# Enable CTest
-enable_testing()
+# enable_testing()
diff --git a/cmake/defaults/clangdefaults.cmake b/cmake/defaults/clangdefaults.cmake
index 3295342121..5fb8e50636 100644
--- a/cmake/defaults/clangdefaults.cmake
+++ b/cmake/defaults/clangdefaults.cmake
@@ -21,14 +21,10 @@
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
-# By default, Release flavor builds in cmake set NDEBUG, which
-# breaks things internally. Turn it off.
-set(CMAKE_CXX_FLAGS_RELEASE "-O2")
-# Initialize to c++11, pxr won't build without it.
-set(_PXR_CXX_FLAGS "-std=c++11 -DTF_NO_GNU_EXT -Wall -Wno-unused-local-typedefs")
-
-# We use hash_map, suppress deprecation warning.
-_add_warning_flag("no-deprecated")
-_add_warning_flag("no-deprecated-declarations")
+include(gccclangshareddefaults)
+# Defining TF_NO_GNU_EXT disables using the gnu hash_set and
+# hash_map containers on platforms where we can't. The implementation
+# will substitute C++11 containers with equivalent semantics in this case.
+set(_PXR_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS} -DTF_NO_GNU_EXT")
diff --git a/cmake/defaults/gccclangshareddefaults.cmake b/cmake/defaults/gccclangshareddefaults.cmake
new file mode 100644
index 0000000000..449ccd2edf
--- /dev/null
+++ b/cmake/defaults/gccclangshareddefaults.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright 2016 Pixar
+#
+# Licensed under the Apache License, Version 2.0 (the "Apache License")
+# with the following modification; you may not use this file except in
+# compliance with the Apache License and the following modification to it:
+# Section 6. Trademarks. is deleted and replaced with:
+#
+# 6. Trademarks. This License does not grant permission to use the trade
+# names, trademarks, service marks, or product names of the Licensor
+# and its affiliates, except as required to comply with Section 4(c) of
+# the License and to reproduce the content of the NOTICE file.
+#
+# You may obtain a copy of the Apache License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the Apache License with the above modification is
+# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the Apache License for the specific
+# language governing permissions and limitations under the Apache License.
+#
+
+# This file contains a set of flags/settings shared between our
+# GCC and Clang configs. This allows clangdefaults and gccdefaults
+# to remain minimal, marking the points where divergence is required.
+include(Options)
+
+# By default, Release flavor builds in cmake set NDEBUG, which
+# breaks things internally. Turn it off.
+set(CMAKE_CXX_FLAGS_RELEASE "-O2")
+
+# Enable all warnings
+_add_warning_flag("all")
+# We use hash_map, suppress deprecation warning.
+_add_warning_flag("no-deprecated")
+_add_warning_flag("no-deprecated-declarations")
+# Suppress unused typedef warnings eminating from boost.
+_add_warning_flag("no-unused-local-typedefs")
+
+# Turn on C++11, pxr won't build without it.
+set(_PXR_GCC_CLANG_SHARED_CXX_FLAGS "-std=c++11")
+
+if (${PXR_MAYA_TBB_BUG_WORKAROUND})
+ set(_PXR_GCC_CLANG_SHARED_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS} -Wl,-Bsymbolic")
+endif()
+
+if (${PXR_STRICT_BUILD_MODE})
+ _add_warning_flag("error")
+endif()
diff --git a/cmake/defaults/gccdefaults.cmake b/cmake/defaults/gccdefaults.cmake
index decf1e7917..ce7789a2c5 100644
--- a/cmake/defaults/gccdefaults.cmake
+++ b/cmake/defaults/gccdefaults.cmake
@@ -21,15 +21,7 @@
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
-# By default, Release flavor builds in cmake set NDEBUG, which
-# breaks things internally. Turn it off.
-set(CMAKE_CXX_FLAGS_RELEASE "-O2")
-# Initialize to c++11, pxr won't build without it.
-# Turn on all warnings and convert them to errors.
-set(_PXR_CXX_FLAGS "-std=c++11 -Wall -Wno-unused-local-typedefs")
-
-# We use hash_map, suppress deprecation warning.
-_add_warning_flag("no-deprecated")
-_add_warning_flag("no-deprecated-declarations")
+include(gccclangshareddefaults)
+set(_PXR_CXX_FLAGS "${_PXR_GCC_CLANG_SHARED_CXX_FLAGS}")
diff --git a/cmake/defaults/msvcdefaults.cmake b/cmake/defaults/msvcdefaults.cmake
index dcba7cfa78..e29209fef4 100644
--- a/cmake/defaults/msvcdefaults.cmake
+++ b/cmake/defaults/msvcdefaults.cmake
@@ -22,9 +22,67 @@
# language governing permissions and limitations under the Apache License.
#
+# Make sure WinDef.h does not define min and max macros which
+# will conflict with std::min() and std::max().
+add_definitions("/DNOMINMAX")
+
+# TBB conflict
+# This needs to be enabled only for debug builds
+# add_definitions("/DTBB_USE_DEBUG=1")
+
+# Allow "Unsecure" STL
+add_definitions("/D_SCL_SECURE_NO_WARNINGS")
+
+# Needed for consistency with Linux for the use of hashmap and hashset
+add_definitions("/DTF_NO_GNU_EXT")
+
+# Needed to prevent YY files trying to import Unistd.h
+# (which doesn't exist on Windows)
+add_definitions("/DYY_NO_UNISTD_H")
+
+# Forces all libraries that have separate source, to be linked as
+# DLL's rather than static libraries on Microsoft Window.
+add_definitions("/DBOOST_ALL_DYN_LINK")
+
+add_definitions("/DBUILD_OPTLEVEL_OPT")
+
+add_definitions(/"DFLAVOR=\"win64\"")
+
+add_definitions(/"DOPENEXR_DLL")
+
# Set a decent warning level
add_definitions("/W3")
# Treat all warnings as errors
add_definitions("/WX")
+# trunctation from 'double' to 'float' due to matrix and vector classes in `Gf`
+add_definitions("/wd4244")
+add_definitions("/wd4305")
+
+# conversion from size_t to int. Whilst we don't want this enabled
+# its in the Python headers. So all the Python wrap code is affected.
+add_definitions("/wd4267")
+
+# no definition for inline function
+# this affects Glf only
+add_definitions("/wd4506")
+
+# Enable PDB generation
+add_definitions("/Zi")
+
+# Enable minimum builds
+add_definitions("/Gm")
+
+# These files require /bigobj compiler flag
+# Vt/arrayPyBuffer.cpp
+# Usd/crateFile.cpp
+# Usd/stage.cpp
+# Until we can set the flag on a per file basis, we'll have to enable it
+# for all translation units.
+add_definitions("/bigobj")
+
+if (${PXR_STRICT_BUILD_MODE})
+ # Treat all warnings as errors
+ add_definitions("/WX")
+endif()
diff --git a/cmake/macros/Private.cmake b/cmake/macros/Private.cmake
index 3ca3eb990b..cf29c3a381 100644
--- a/cmake/macros/Private.cmake
+++ b/cmake/macros/Private.cmake
@@ -111,11 +111,7 @@ function(_install_python LIBRARY_NAME)
)
set(libPythonPrefix lib/python)
-
- string(SUBSTRING ${LIBRARY_NAME} 0 1 LIBNAME_FL)
- string(TOUPPER ${LIBNAME_FL} LIBNAME_FL)
- string(SUBSTRING ${LIBRARY_NAME} 1 -1 LIBNAME_SUFFIX)
- set(LIBRARY_INSTALLNAME "${LIBNAME_FL}${LIBNAME_SUFFIX}")
+ _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME)
foreach(file ${ip_FILES})
set(filesToInstall "")
@@ -221,6 +217,36 @@ function(_install_resource_files)
endforeach()
endfunction() # _install_resource_files
+function(_install_pyside_ui_files)
+ set(uiFiles "")
+ foreach(uiFile ${ARGN})
+ get_filename_component(outFileName ${uiFile} NAME_WE)
+ get_filename_component(uiFilePath ${uiFile} ABSOLUTE)
+ set(outFilePath "${CMAKE_CURRENT_BINARY_DIR}/${outFileName}.py")
+ add_custom_command(
+ OUTPUT ${outFilePath}
+ COMMAND "${PYSIDEUICBINARY}"
+ ARGS -o ${outFilePath} ${uiFilePath}
+ MAIN_DEPENDENCY "${uiFilePath}"
+ COMMENT "Generating Python for ${uiFilePath} ..."
+ VERBATIM
+ )
+ list(APPEND uiFiles ${outFilePath})
+ endforeach()
+
+ add_custom_target(${LIBRARY_NAME}_pysideuifiles ALL
+ DEPENDS ${uiFiles}
+ )
+
+ set(libPythonPrefix lib/python)
+ _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME)
+
+ install(
+ FILES ${uiFiles}
+ DESTINATION "${libPythonPrefix}/pxr/${LIBRARY_INSTALLNAME}"
+ )
+endfunction() # _install_pyside_ui_files
+
function(_classes LIBRARY_NAME)
# Install headers to build or install prefix
set(options PUBLIC PRIVATE)
diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake
index e9c6ad2cd5..26419aa5a9 100644
--- a/cmake/macros/Public.cmake
+++ b/cmake/macros/Public.cmake
@@ -41,6 +41,18 @@ function(pxr_python_bins)
DESTINATION ${installDir}
RENAME ${file}
)
+
+ # Windows by default cannot execute Python files so here
+ # we create a batch file wrapper that invokes the python
+ # files.
+ if(WIN32)
+ file(WRITE "${CMAKE_BINARY_DIR}/${pyFile}.cmd" "@set PATH=C:\\Program Files\\usd\\lib;%PATH%\r\npython ${file} %*")
+ install(PROGRAMS
+ "${CMAKE_BINARY_DIR}/${pyFile}.cmd"
+ DESTINATION ${installDir}
+ RENAME "${file}.cmd"
+ )
+ endif()
endforeach()
endfunction() # pxr_install_python_bins
@@ -96,6 +108,32 @@ function(pxr_cpp_bin BIN_NAME)
endfunction()
+function(pxr_add_filename_property LIBRARY_NAME FILELIST)
+ foreach(cppfile ${FILELIST})
+
+ get_filename_component(fileExt "${cppfile}" EXT)
+
+ if("${fileExt}" STREQUAL "")
+ get_filename_component(
+ cppModuleName
+ "${cppfile}"
+ NAME_WE)
+
+ set_source_files_properties(${cppfile}.cpp PROPERTIES COMPILE_FLAGS
+ -D__FILENAME__=${LIBRARY_NAME}${cppModuleName})
+
+ elseif(fileExt MATCHES .cpp)
+ get_filename_component(
+ cppModuleName
+ "${cppfile}"
+ NAME_WE)
+
+ set_source_files_properties(${cppfile} PROPERTIES COMPILE_FLAGS
+ -D__FILENAME__=${LIBRARY_NAME}${cppModuleName})
+ endif()
+ endforeach()
+endfunction()
+
function(pxr_shared_library LIBRARY_NAME)
set(options PYTHON_LIBRARY)
set(multiValueArgs
@@ -106,6 +144,7 @@ function(pxr_shared_library LIBRARY_NAME)
CPPFILES
PYMODULE_CPPFILES
PYTHON_FILES
+ PYSIDE_UI_FILES
LIBRARIES
INCLUDE_DIRS
RESOURCE_FILES
@@ -135,6 +174,24 @@ function(pxr_shared_library LIBRARY_NAME)
${sl_PRIVATE_HEADERS} ${${LIBRARY_NAME}_PRIVATE_HEADERS}
)
+ if(sl_CPPFILES)
+ pxr_add_filename_property(${LIBRARY_NAME} "${sl_CPPFILES}")
+ endif()
+ if(sl_PRIVATE_CLASSES)
+ pxr_add_filename_property(${LIBRARY_NAME} "${sl_PRIVATE_CLASSES}")
+ endif()
+ if(sl_PUBLIC_CLASSES)
+ pxr_add_filename_property(${LIBRARY_NAME} "${sl_PUBLIC_CLASSES}")
+ endif()
+
+ if(WIN32)
+ if(MSVC)
+ set_target_properties(
+ ${LIBRARY_NAME}
+ PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
+ endif()
+ endif()
+
if(sl_PYTHON_FILES)
_install_python(${LIBRARY_NAME}
FILES ${sl_PYTHON_FILES}
@@ -169,12 +226,24 @@ function(pxr_shared_library LIBRARY_NAME)
set(rpath "$ORIGIN/../../../../${PXR_INSTALL_SUBDIR}/lib:${rpath}")
endif()
- set_target_properties(${LIBRARY_NAME}
- PROPERTIES
- PREFIX ""
- FOLDER "${PXR_PREFIX}/_python"
- INSTALL_RPATH ${rpath}
- )
+ if(WIN32)
+ add_definitions(-D_BUILDING_PYD=1)
+ set_target_properties(${LIBRARY_NAME}
+ PROPERTIES
+ PREFIX ""
+ SUFFIX ".pyd"
+ FOLDER "${PXR_PREFIX}/_python"
+ LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS"
+ )
+ else()
+ set_target_properties(${LIBRARY_NAME}
+ PROPERTIES
+ PREFIX ""
+ SUFFIX ".pyd"
+ FOLDER "${PXR_PREFIX}/_python"
+ INSTALL_RPATH ${rpath}
+ )
+ endif()
else()
_get_install_dir(lib LIB_INSTALL_PREFIX)
_get_share_install_dir(SHARE_INSTALL_PREFIX)
@@ -201,9 +270,14 @@ function(pxr_shared_library LIBRARY_NAME)
set(installLocation ${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX})
endif()
+ if(WIN32)
+ set(_PxrUserLocation "$ENV{ProgramData}\\usd\\plugins")
+ else()
+ set(_PxrUserLocation "/usr/local/share/usd/plugins")
+ endif()
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
- "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=/usr/local/share/usd/plugins;PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_INSTALL_LOCATION=${installLocation}"
+ "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=${_PxrUserLocation};PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_INSTALL_LOCATION=${installLocation}"
)
# Always bake the rpath.
@@ -257,8 +331,10 @@ function(pxr_shared_library LIBRARY_NAME)
install(TARGETS ${LIBRARY_NAME}
EXPORT pxrTargets
+ ARCHIVE DESTINATION ${LIB_INSTALL_PREFIX}
LIBRARY DESTINATION ${LIB_INSTALL_PREFIX}
ARCHIVE DESTINATION ${LIB_INSTALL_PREFIX}
+ RUNTIME DESTINATION ${LIB_INSTALL_PREFIX}
PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_PREFIX}
)
@@ -301,6 +377,11 @@ function(pxr_shared_library LIBRARY_NAME)
if (sl_RESOURCE_FILES)
_install_resource_files(${sl_RESOURCE_FILES})
endif()
+
+ if (sl_PYSIDE_UI_FILES)
+ _install_pyside_ui_files(${sl_PYSIDE_UI_FILES})
+ endif()
+
endfunction() # pxr_shared_library
function(pxr_static_library LIBRARY_NAME)
@@ -449,6 +530,7 @@ function(pxr_plugin PLUGIN_NAME)
CPPFILES
PYMODULE_CPPFILES
PYTHON_FILES
+ PYSIDE_UI_FILES
LIBRARIES
INCLUDE_DIRS
RESOURCE_FILES
@@ -563,6 +645,7 @@ function(pxr_plugin PLUGIN_NAME)
install(TARGETS ${PLUGIN_NAME}
EXPORT pxrTargets
+ ARCHIVE DESTINATION ${PLUGIN_INSTALL_PREFIX}
LIBRARY DESTINATION ${PLUGIN_INSTALL_PREFIX}
ARCHIVE DESTINATION ${PLUGIN_INSTALL_PREFIX}
PUBLIC_HEADER DESTINATION ${HEADER_INSTALL_PREFIX}
@@ -601,6 +684,13 @@ function(pxr_plugin PLUGIN_NAME)
_install_resource_files(${sl_RESOURCE_FILES})
endif()
+ if (sl_PYSIDE_UI_FILES)
+ _get_install_dir(plugin PLUGINS_PREFIX)
+ set(LIBRARY_NAME ${PLUGIN_NAME})
+
+ _install_pyside_ui_files(${sl_PYSIDE_UI_FILES})
+ endif()
+
# Build python module.
if(DEFINED sl_PYMODULE_CPPFILES)
pxr_shared_library(
@@ -698,6 +788,7 @@ function(pxr_build_test_shared_lib LIBRARY_NAME)
)
install(TARGETS ${LIBRARY_NAME}
+ ARCHIVE DESTINATION "tests/lib"
LIBRARY DESTINATION "tests/lib"
ARCHIVE DESTINATION "tests/lib"
)
@@ -744,7 +835,7 @@ endfunction() # pxr_test_scripts
function(pxr_install_test_dir)
cmake_parse_arguments(bt
- ""
+ ""
"SRC;DEST"
""
${ARGN}
@@ -758,13 +849,13 @@ endfunction() # pxr_install_test_dir
function(pxr_register_test TEST_NAME)
cmake_parse_arguments(bt
- "PYTHON"
+ "PYTHON"
"COMMAND;STDOUT_REDIRECT;STDERR_REDIRECT;DIFF_COMPARE;EXPECTED_RETURN_CODE;TESTENV"
"ENV"
${ARGN}
)
- # This harness is a filter which allows us to manipulate the test run,
+ # This harness is a filter which allows us to manipulate the test run,
# e.g. by changing the environment, changing the expected return code, etc.
set(testWrapperCmd ${PROJECT_SOURCE_DIR}/cmake/macros/testWrapper.py --verbose)
@@ -799,7 +890,7 @@ function(pxr_register_test TEST_NAME)
endif()
if (bt_EXPECTED_RETURN_CODE)
- set(testWrapperCmd ${testWrapperCmd}
+ set(testWrapperCmd ${testWrapperCmd}
--expected-return-code=${bt_EXPECTED_RETURN_CODE})
endif()
@@ -846,7 +937,7 @@ function(pxr_katana_nodetypes NODE_TYPES)
set(importLines "import ${nodeType}\n")
endforeach()
- install(PROGRAMS
+ install(PROGRAMS
${pyFiles}
DESTINATION ${installDir}
)
diff --git a/cmake/modules/FindMaya.cmake b/cmake/modules/FindMaya.cmake
index 20cccbdce7..66d289f2e1 100644
--- a/cmake/modules/FindMaya.cmake
+++ b/cmake/modules/FindMaya.cmake
@@ -86,6 +86,7 @@ if(WIN32)
HINTS
"${MAYA_LOCATION}"
"$ENV{MAYA_LOCATION}"
+ "C:/Program Files/Autodesk/Maya2016"
"C:/Program Files/Autodesk/Maya2015.5-x64"
"C:/Program Files/Autodesk/Maya2015.5"
"C:/Program Files/Autodesk/Maya2014.5-x64"
diff --git a/cmake/modules/FindOpenEXR.cmake b/cmake/modules/FindOpenEXR.cmake
index 3d815b34cc..337c85a69e 100644
--- a/cmake/modules/FindOpenEXR.cmake
+++ b/cmake/modules/FindOpenEXR.cmake
@@ -21,12 +21,6 @@
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
-find_path(OPENEXR_ROOT_DIR
- include/OpenEXR/half.h
- HINTS
- "${OPENEXR_LOCATION}"
- "$ENV{OPENEXR_LOCATION}"
-)
if (APPLE)
find_path(OPENEXR_LIBRARY_DIR
@@ -119,7 +113,6 @@ list(APPEND OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR}/OpenEXR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenEXR
REQUIRED_VARS
- OPENEXR_ROOT_DIR
OPENEXR_INCLUDE_DIRS
OPENEXR_LIBRARY_DIR
VERSION_VAR
diff --git a/cmake/modules/FindOpenImageIO.cmake b/cmake/modules/FindOpenImageIO.cmake
index d4680cd940..0dde6cc89c 100644
--- a/cmake/modules/FindOpenImageIO.cmake
+++ b/cmake/modules/FindOpenImageIO.cmake
@@ -21,6 +21,7 @@
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#
+
if(UNIX)
find_path(OIIO_BASE_DIR
include/OpenImageIO/oiioversion.h
@@ -40,7 +41,25 @@ if(UNIX)
DOC
"OpenImageIO library path"
)
-endif(UNIX)
+elseif(WIN32)
+ find_path(OIIO_BASE_DIR
+ include/OpenImageIO/oiioversion.h
+ HINTS
+ "${OIIO_LOCATION}"
+ "$ENV{OIIO_LOCATION}"
+ )
+ find_path(OIIO_LIBRARY_DIR
+ OpenImageIO.lib
+ HINTS
+ "${OIIO_LOCATION}"
+ "$ENV{OIIO_LOCATION}"
+ "${OIIO_BASE_DIR}"
+ PATH_SUFFIXES
+ lib/
+ DOC
+ "OpenImageIO library path"
+ )
+endif()
find_path(OIIO_INCLUDE_DIR
OpenImageIO/oiioversion.h
diff --git a/cmake/modules/FindPySide.cmake b/cmake/modules/FindPySide.cmake
new file mode 100644
index 0000000000..b5722fb44f
--- /dev/null
+++ b/cmake/modules/FindPySide.cmake
@@ -0,0 +1,42 @@
+#
+# Copyright 2016 Pixar
+#
+# Licensed under the Apache License, Version 2.0 (the "Apache License")
+# with the following modification; you may not use this file except in
+# compliance with the Apache License and the following modification to it:
+# Section 6. Trademarks. is deleted and replaced with:
+#
+# 6. Trademarks. This License does not grant permission to use the trade
+# names, trademarks, service marks, or product names of the Licensor
+# and its affiliates, except as required to comply with Section 4(c) of
+# the License and to reproduce the content of the NOTICE file.
+#
+# You may obtain a copy of the Apache License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the Apache License with the above modification is
+# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the Apache License for the specific
+# language governing permissions and limitations under the Apache License.
+#
+if (NOT PYTHON_EXECUTABLE)
+ return()
+endif()
+
+find_program(PYSIDEUICBINARY
+ NAMES pyside-uic
+ HINTS ${PYSIDE_BIN_DIR}
+)
+
+execute_process(
+ COMMAND
+ "${PYTHON_EXECUTABLE}" "-c" "import PySide"
+ RESULT_VARIABLE
+ pySideImportResult
+)
+
+if (pySideImportResult EQUAL 0 AND EXISTS(${PYSIDEUICBINARY}))
+ set(PYSIDE_FOUND True)
+endif()
diff --git a/cmake/modules/FindPySideTools.cmake b/cmake/modules/FindPySideTools.cmake
deleted file mode 100644
index c5028c54cb..0000000000
--- a/cmake/modules/FindPySideTools.cmake
+++ /dev/null
@@ -1,94 +0,0 @@
-# Try to find PySide utilities, PYSIDEUIC4 and PYSIDERCC4:
-# PYSIDEUIC4BINARY - Location of PYSIDEUIC4 executable
-# PYSIDERCC4BINARY - Location of PYSIDERCC4 executable
-# PYSIDE_TOOLS_FOUND - PySide utilities found.
-
-# Also provides macro similar to FindQt4.cmake's WRAP_UI and WRAP_RC,
-# for the automatic generation of Python code from Qt4's user interface
-# ('.ui') and resource ('.qrc') files. These macros are called:
-# - PYSIDE_WRAP_UI
-# - PYSIDE_WRAP_RC
-# XXX - from https://github.com/yorikvanhavre/FreeCAD/blob/master/cMake/FindPySideTools.cmake
-# License?
-
-if(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY)
- # Already in cache, be silent
- set(PYSIDE_TOOLS_FOUND_QUIETLY TRUE)
-endif(PYSIDEUIC4BINARY AND PYSIDERCC4BINARY)
-
-find_program(PYSIDEUIC4BINARY
- NAMES pyside-uic pyside-uic-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}
- HINTS ${PYSIDE_BIN_DIR}
-)
-find_program(PYSIDERCC4BINARY
- NAMES pyside-rcc pyside-rcc-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}
- HINTS ${PYSIDE_BIN_DIR}
-)
-
-macro(PYSIDE_WRAP_UI LIBRARY_NAME)
- set(outfiles "")
- foreach(it ${ARGN})
- get_filename_component(outfile ${it} NAME_WE)
- get_filename_component(infile ${it} ABSOLUTE)
- set(outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile}.py)
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${PYSIDEUIC4BINARY} ${infile} -o ${outfile}
- MAIN_DEPENDENCY ${infile}
- )
- list(APPEND outfiles ${outfile})
- endforeach() # it
-
- add_custom_target(${LIBRARY_NAME}_pysideuicfiles
- ALL
- DEPENDS ${outfiles}
- )
- install(FILES ${outfiles}
- DESTINATION "lib/python/pxr/${LIBRARY_NAME}"
- )
-endmacro() # PYSIDE_WRAP_UI
-
-#XXX -- i haven't fixed this function from the source, but
-# wrap_ui was so broken, i suspect this one is too
-MACRO(PYSIDE_WRAP_RC outfiles)
- FOREACH(it ${ARGN})
- GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
- GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
- SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py)
- #ADD_CUSTOM_TARGET(${it} ALL
- # DEPENDS ${outfile}
- #)
- if(WIN32)
- ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
- COMMAND ${PYSIDERCC4BINARY} ${infile} -o ${outfile}
- MAIN_DEPENDENCY ${infile}
- )
- else(WIN32)
- # Especially on Open Build Service we don't want changing date like
- # pyside-rcc generates in comments at beginning.
- EXECUTE_PROCESS(
- COMMAND ${PYSIDERCC4BINARY} ${infile}
- COMMAND sed "/^# /d"
- OUTPUT_FILE ${outfile}
- )
- endif(WIN32)
- SET(${outfiles} ${${outfiles}} ${outfile})
- ENDFOREACH(it)
-ENDMACRO (PYSIDE_WRAP_RC)
-
-IF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY})
- set(PYSIDE_TOOLS_FOUND TRUE)
-ENDIF(EXISTS ${PYSIDEUIC4BINARY} AND EXISTS ${PYSIDERCC4BINARY})
-
-if(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
- if (NOT PySideTools_FIND_QUIETLY)
- message(STATUS "Found PySide Tools: ${PYSIDEUIC4BINARY}, ${PYSIDERCC4BINARY}")
- endif (NOT PySideTools_FIND_QUIETLY)
-else(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
- if(PySideTools_FIND_REQUIRED)
- message(FATAL_ERROR "PySideTools could not be found, but are required.")
- else(PySideTools_FIND_REQUIRED)
- if (NOT PySideTools_FIND_QUIETLY)
- message(STATUS "PySideTools: not found.")
- endif (NOT PySideTools_FIND_QUIETLY)
- endif(PySideTools_FIND_REQUIRED)
-endif(PYSIDERCC4BINARY AND PYSIDEUIC4BINARY)
diff --git a/extras/usd/examples/CMakeLists.txt b/extras/usd/examples/CMakeLists.txt
index 51782b9f73..5cb4dd8c47 100644
--- a/extras/usd/examples/CMakeLists.txt
+++ b/extras/usd/examples/CMakeLists.txt
@@ -1,6 +1,8 @@
set(PXR_PREFIX examples)
set(PXR_INSTALL_SUBDIR share/usd/examples)
-add_subdirectory(usdObj)
-add_subdirectory(usdSchemaExamples)
-add_subdirectory(usdMakeFileVariantModelAsset)
+if(UNIX)
+ add_subdirectory(usdObj)
+ add_subdirectory(usdSchemaExamples)
+ add_subdirectory(usdMakeFileVariantModelAsset)
+endif()
\ No newline at end of file
diff --git a/extras/usd/examples/usdSchemaExamples/tokens.h b/extras/usd/examples/usdSchemaExamples/tokens.h
index ce731abd25..ab91a39209 100644
--- a/extras/usd/examples/usdSchemaExamples/tokens.h
+++ b/extras/usd/examples/usdSchemaExamples/tokens.h
@@ -24,6 +24,8 @@
#ifndef USDSCHEMAEXAMPLES_TOKENS_H
#define USDSCHEMAEXAMPLES_TOKENS_H
+/// \file usdSchemaExamples/tokens.h
+
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
// This is an automatically generated file (by usdGenSchema.py).
@@ -33,8 +35,6 @@
#include "pxr/base/tf/staticTokens.h"
-/// \file ./tokens.h
-
/// \hideinitializer
#define USDSCHEMAEXAMPLES_TOKENS \
(complexString) \
@@ -45,7 +45,8 @@
(target)
/// \anchor UsdSchemaExamplesTokens
-/// \brief UsdSchemaExamplesTokens provides static, efficient TfToken's for
+///
+/// UsdSchemaExamplesTokens provides static, efficient TfToken's for
/// use in all public USD API
///
/// These tokens are auto-generated from the module's schema, representing
diff --git a/pxr/base/lib/arch/CMakeLists.txt b/pxr/base/lib/arch/CMakeLists.txt
index 1d4b3171df..8f21a47e23 100644
--- a/pxr/base/lib/arch/CMakeLists.txt
+++ b/pxr/base/lib/arch/CMakeLists.txt
@@ -4,11 +4,22 @@ set(CMAKE_INCLUDE_CURRENT_DIR OFF)
set(PXR_PREFIX pxr/base)
set(PXR_PACKAGE arch)
+if(WIN32)
+ set(MODULE_ENTRYPOINT_CPP DllMain.cpp)
+ set(PLATFORM_ATTRIBUTES_H attributesWindows.h)
+ set(WINLIBS Ws2_32.lib)
+ set(DEBUG_HELP Dbghelp.lib)
+else()
+ set(MATHLIB ${M_LIB})
+endif()
+
pxr_shared_library(arch
LIBRARIES
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS}
- ${M_LIB}
+ ${WINLIBS}
+ ${MATHLIB}
+ ${DEBUG_HELP}
PUBLIC_CLASSES
daemon
@@ -30,13 +41,17 @@ pxr_shared_library(arch
PUBLIC_HEADERS
align.h
+ api.h
attributes.h
+ ${PLATFORM_ATTRIBUTES_H}
buildMode.h
defines.h
+ env.h
export.h
functionLite.h
hints.h
inttypes.h
+ library.h
math.h
pragmas.h
@@ -45,140 +60,145 @@ pxr_shared_library(arch
CPPFILES
assumptions.cpp
+ env.cpp
+ ${MODULE_ENTRYPOINT_CPP}
initConfig.cpp
+ library.cpp
)
-pxr_build_test_shared_lib(testArchAbiPlugin
- CPPFILES
- testenv/testArchAbiPlugin.cpp
-)
-pxr_build_test(testArchAbi
- LIBRARIES
- arch
- CPPFILES
- testenv/testArchAbi.cpp
-)
-pxr_build_test(testArchAttributes
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testAttributes.cpp
-)
-pxr_build_test(testArchDemangle
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testDemangle.cpp
-)
-pxr_build_test(testArchError
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testError.cpp
-)
-pxr_build_test(testArchErrno
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testErrno.cpp
-)
-pxr_build_test(testArchFileSystem
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testFileSystem.cpp
-)
-pxr_build_test(testArchFunction
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testFunction.cpp
-)
-pxr_build_test(testArchStackTrace
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testStackTrace.cpp
-)
-pxr_build_test(testArchSymbols
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testSymbols.cpp
-)
-pxr_build_test(testArchSystemInfo
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testSystemInfo.cpp
-)
-pxr_build_test(testArchThreads
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testThreads.cpp
-)
-pxr_build_test(testArchTiming
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testTiming.cpp
-)
-pxr_build_test(testArchVsnprintf
- LIBRARIES
- arch
- ${CMAKE_DL_LIBS}
- CPPFILES
- testenv/testVsnprintf.cpp
-)
+if(UNIX)
+ pxr_build_test_shared_lib(testArchAbiPlugin
+ CPPFILES
+ testenv/testArchAbiPlugin.cpp
+ )
+ pxr_build_test(testArchAbi
+ LIBRARIES
+ arch
+ CPPFILES
+ testenv/testArchAbi.cpp
+ )
+ pxr_build_test(testArchAttributes
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testAttributes.cpp
+ )
+ pxr_build_test(testArchDemangle
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testDemangle.cpp
+ )
+ pxr_build_test(testArchError
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testError.cpp
+ )
+ pxr_build_test(testArchErrno
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testErrno.cpp
+ )
+ pxr_build_test(testArchFileSystem
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testFileSystem.cpp
+ )
+ pxr_build_test(testArchFunction
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testFunction.cpp
+ )
+ pxr_build_test(testArchStackTrace
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testStackTrace.cpp
+ )
+ pxr_build_test(testArchSymbols
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testSymbols.cpp
+ )
+ pxr_build_test(testArchSystemInfo
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testSystemInfo.cpp
+ )
+ pxr_build_test(testArchThreads
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testThreads.cpp
+ )
+ pxr_build_test(testArchTiming
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testTiming.cpp
+ )
+ pxr_build_test(testArchVsnprintf
+ LIBRARIES
+ arch
+ ${CMAKE_DL_LIBS}
+ CPPFILES
+ testenv/testVsnprintf.cpp
+ )
-pxr_register_test(testArchAbi
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAbi"
-)
-pxr_register_test(testArchAttributes
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAttributes"
-)
-pxr_register_test(testArchDemangle
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchDemangle"
-)
-pxr_register_test(testArchError
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchError"
-)
-pxr_register_test(testArchErrno
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchErrno"
-)
-pxr_register_test(testArchFileSystem
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFileSystem"
-)
-pxr_register_test(testArchFunction
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFunction"
-)
-pxr_register_test(testArchStackTrace
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchStackTrace"
-)
-pxr_register_test(testArchSymbols
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSymbols"
-)
-pxr_register_test(testArchSystemInfo
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSystemInfo"
-)
-pxr_register_test(testArchTiming
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchTiming"
-)
-pxr_register_test(testArchThreads
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchThreads"
-)
-pxr_register_test(testArchVsnprintf
- COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchVsnprintf"
-)
+ pxr_register_test(testArchAbi
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAbi"
+ )
+ pxr_register_test(testArchAttributes
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchAttributes"
+ )
+ pxr_register_test(testArchDemangle
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchDemangle"
+ )
+ pxr_register_test(testArchError
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchError"
+ )
+ pxr_register_test(testArchErrno
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchErrno"
+ )
+ pxr_register_test(testArchFileSystem
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFileSystem"
+ )
+ pxr_register_test(testArchFunction
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchFunction"
+ )
+ pxr_register_test(testArchStackTrace
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchStackTrace"
+ )
+ pxr_register_test(testArchSymbols
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSymbols"
+ )
+ pxr_register_test(testArchSystemInfo
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchSystemInfo"
+ )
+ pxr_register_test(testArchTiming
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchTiming"
+ )
+ pxr_register_test(testArchThreads
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchThreads"
+ )
+ pxr_register_test(testArchVsnprintf
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testArchVsnprintf"
+ )
+endif()
\ No newline at end of file
diff --git a/pxr/base/lib/arch/DllMain.cpp b/pxr/base/lib/arch/DllMain.cpp
new file mode 100644
index 0000000000..6e6fd9e32a
--- /dev/null
+++ b/pxr/base/lib/arch/DllMain.cpp
@@ -0,0 +1,49 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#include
+#include "pxr/base/arch/attributes.h"
+
+BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved)
+{
+ UNREFERENCED_PARAMETER(module);
+ UNREFERENCED_PARAMETER(reserved);
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ archRunConstructors();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ archRunDestructors();
+ break;
+ }
+ return TRUE;
+}
diff --git a/pxr/base/lib/arch/align.h b/pxr/base/lib/arch/align.h
index 74af9842a7..89aab2e3f1 100644
--- a/pxr/base/lib/arch/align.h
+++ b/pxr/base/lib/arch/align.h
@@ -24,6 +24,10 @@
#ifndef ARCH_ALIGN_H
#define ARCH_ALIGN_H
+/// \file arch/align.h
+/// \ingroup group_arch_Memory
+/// Provide architecture-specific memory-alignment information.
+
#if !defined(__cplusplus)
#error This include file can only be included in C++ programs.
#endif
@@ -32,51 +36,34 @@
#include
#include
-/*!
- * \file align.h
- * \brief Provide architecture-specific memory-alignment information.
- * \ingroup group_arch_Memory
- */
-
-/*
- * This is valid on all our current platforms, both for 32-bit and
- * 64-bit compiles.
- */
-
-/*!
- * \brief Return suitably aligned memory size.
- * \ingroup group_arch_Memory
- *
- * Requests to \c malloc() or \c ::new for a given size are often
- * rounded upward. Given a request for \c nBytes bytes of storage,
- * this function returns the amount that would actually be consumed
- * by the system to satisfy it. This is needed for efficient user-defined
- * memory management (which you should \e NOT do yourself: see
- * instead \c classAllocator.h). [Ensure this filename is correct]
- */
+/// \addtogroup group_arch_Memory
+///@{
+/// Return suitably aligned memory size.
+///
+/// Requests to \c malloc() or \c ::new for a given size are often rounded
+/// upward. Given a request for \c nBytes bytes of storage, this function
+/// returns the amount that would actually be consumed by the system to
+/// satisfy it. This is needed for efficient user-defined memory management.
+///
inline size_t
ArchAlignMemorySize(size_t nBytes) {
return (nBytes + 7) & (~0x7);
}
-/*!
- * \brief Maximum extra space needed for alignment.
- * \ingroup group_arch_Memory
- * \hideinitializer
- *
- * The \c ArchAlignMemorySize() can increase the required memory by no more
- * than \c ARCH_MAX_ALIGNMENT_INCREASE.
- */
+/// Maximum extra space needed for alignment.
+///
+/// The \c ArchAlignMemorySize() can increase the required memory by no more
+/// than \c ARCH_MAX_ALIGNMENT_INCREASE.
+///
+/// \hideinitializer
#define ARCH_MAX_ALIGNMENT_INCREASE 7
-/*!
- * \brief Align memory to the next "best" alignment value.
- * \ingroup group_arch_Memory
- *
- * This will take a pointer and bump it to the next ideal alignment boundary
- * that will work for all data types.
- */
+/// Align memory to the next "best" alignment value.
+///
+/// This will take a pointer and bump it to the next ideal alignment boundary
+/// that will work for all data types.
+///
inline void *
ArchAlignMemory(void *base)
{
@@ -84,13 +71,11 @@ ArchAlignMemory(void *base)
((reinterpret_cast(base) + 7) & ~0x7);
}
-/*!
- * \brief The size of a CPU cache line in bytes.
- * \ingroup group_arch_Memory
- *
- * The size of a CPU cache line on the current processor architecture in bytes.
- */
+/// The size of a CPU cache line on the current processor architecture in bytes.
+///
+/// \hideinitializer
#define ARCH_CACHE_LINE_SIZE 64
+///@}
#endif // ARCH_ALIGN_H
diff --git a/pxr/base/lib/arch/api.h b/pxr/base/lib/arch/api.h
new file mode 100644
index 0000000000..87ffa3537b
--- /dev/null
+++ b/pxr/base/lib/arch/api.h
@@ -0,0 +1,46 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+
+#ifndef ARCH_API_H
+#define ARCH_API_H
+
+#include "pxr/base/arch/export.h"
+
+#if defined(ARCH_STATIC)
+# define ARCH_API
+# define ARCH_LOCAL
+#else
+# if defined(ARCH_EXPORTS)
+# define ARCH_API ARCH_EXPORT
+# define ARCH_API_TEMPLATE_CLASS(...)
+# define ARCH_API_TEMPLATE_STRUCT(...)
+# else
+# define ARCH_API ARCH_IMPORT
+# define ARCH_API_TEMPLATE_CLASS(...) extern template class ARCH_API __VA_ARGS__
+# define ARCH_API_TEMPLATE_STRUCT(...) extern template struct ARCH_API __VA_ARGS__
+# endif
+# define ARCH_LOCAL ARCH_HIDDEN
+#endif
+
+#endif
diff --git a/pxr/base/lib/arch/assumptions.cpp b/pxr/base/lib/arch/assumptions.cpp
index 54f230ee13..97f2ca9212 100644
--- a/pxr/base/lib/arch/assumptions.cpp
+++ b/pxr/base/lib/arch/assumptions.cpp
@@ -28,11 +28,14 @@
#include "pxr/base/arch/export.h"
#include "pxr/base/arch/math.h"
#include
+#include
#if defined(ARCH_OS_LINUX)
#include
#elif defined(ARCH_OS_DARWIN)
#include
+#elif defined(ARCH_OS_WINDOWS)
+#include
#endif
static size_t
@@ -45,6 +48,39 @@ Arch_ObtainCacheLineSize()
size_t cacheLineSizeSize = sizeof(cacheLineSize);
sysctlbyname("hw.cachelinesize", &cacheLineSize, &cacheLineSizeSize, 0, 0);
return cacheLineSize;
+#elif defined(ARCH_OS_DARWIN)
+ size_t cacheLineSize = 0;
+ size_t cacheLineSizeSize = sizeof(cacheLineSize);
+ sysctlbyname("hw.cachelinesize", &cacheLineSize, &cacheLineSizeSize, 0, 0);
+ return cacheLineSize;
+#elif defined(ARCH_OS_WINDOWS)
+ DWORD bufferSize = 0;
+ using INFO = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
+
+ // Get the number of bytes required.
+ ::GetLogicalProcessorInformation(nullptr, &bufferSize);
+
+ // Get the count of structures
+ size_t total = bufferSize / sizeof(INFO);
+
+ // Allocate the array of processor INFOs.
+ std::unique_ptr buffer(new INFO[total]);
+
+ size_t lineSize = 0;
+ if (::GetLogicalProcessorInformation(&buffer[0], &bufferSize))
+ {
+ for (size_t current = 0; current != total; ++current)
+ {
+ if (buffer[current].Relationship == RelationCache &&
+ 1 == buffer[current].Cache.Level)
+ {
+ lineSize = buffer[current].Cache.LineSize;
+ break;
+ }
+ }
+ }
+
+ return lineSize;
#else
#error Arch_ObtainCacheLineSize not implemented for OS.
#endif
@@ -69,12 +105,15 @@ Arch_ValidateAssumptions()
/*
* Some lib/tf coding depends on size_t and long being the same size.
*/
+#if !defined(ARCH_OS_WINDOWS)
if (sizeof(size_t) != sizeof(unsigned long))
- ARCH_ERROR("size_t and unsigned long are different sizes");
+ ARCH_ERROR("size_t and unsigned long are different sizes");
+#endif
/*
* endian.h needs to know how big various types are for its
* swabbing routines.
*/
+#if !defined(ARCH_OS_WINDOWS)
#if defined(ARCH_BITS_64)
if (sizeof(long) != 8)
ARCH_ERROR("sizeof(long) != 8 [64-bit mode]");
@@ -82,7 +121,7 @@ Arch_ValidateAssumptions()
if (sizeof(long) != 4)
ARCH_ERROR("sizeof(long) != 4 [32-bit mode]");
#endif
-
+#endif
/*
* Verify that the exponent and significand of float and double are
* IEEE-754 compliant.
diff --git a/pxr/base/lib/arch/attributes.h b/pxr/base/lib/arch/attributes.h
index ce5914c80f..4f02e65efc 100644
--- a/pxr/base/lib/arch/attributes.h
+++ b/pxr/base/lib/arch/attributes.h
@@ -24,8 +24,24 @@
#ifndef ARCH_ATTRIBUTES_H
#define ARCH_ATTRIBUTES_H
+/// \file arch/attributes.h
+/// Define function attributes.
+///
+/// This file allows you to define architecture-specific or compiler-specific
+/// options to be used outside lib/arch.
+
#include "pxr/base/arch/export.h"
+/*!
+* \brief Macro to stringify a symbol.
+*/
+#define ARCH_STRINGIFY(x) #x
+
+/*!
+* \brief Macro to use for substitution.
+*/
+#define ARCH_PP_EXPAND(x) x
+
/*!
* \file attributes.h
* \brief Define function attributes.
@@ -37,7 +53,109 @@
#if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) || \
defined(doxygen)
-/*!
+/// Macro used to indicate a function takes a printf-like specification.
+///
+/// This attribute is used as follows:
+/// \code
+/// void PrintFunc(T1 arg1, T2 arg2, const char* fmt, ...)
+/// ARCH_PRINTF_FUNCTION(3, 4)
+/// \endcode
+/// This indicates that the third argument is the format string, and that the
+/// fourth argument is where the var-args corresponding to the format string begin.
+///
+/// \hideinitializer
+# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \
+ __attribute__((format(printf, _fmt, _firstArg)))
+
+/// Macro used to indicate a function takes a scanf-like specification.
+///
+/// This attribute is used as follows:
+/// \code
+/// void ScanFunc(T1 arg1, T2 arg2, const char* fmt, ...)
+/// ARCH_PRINTF_FUNCTION(3, 4)
+/// \endcode
+/// This indicates that the third argument is the format string, and
+/// that the fourth argument is where the var-args corresponding to the
+/// format string begin.
+///
+/// \hideinitializer
+# define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \
+ __attribute__((format(scanf, _fmt, _firstArg)))
+
+/// Macro used to indicate that a function should never be inlined.
+///
+/// This attribute is used as follows:
+/// \code
+/// void Func(T1 arg1, T2 arg2) ARCH_NOINLINE;
+/// \endcode
+///
+/// \hideinitializer
+# define ARCH_NOINLINE __attribute__((noinline))
+
+/// Macro used to indicate a function parameter may be unused.
+///
+/// In general, avoid this attribute if possible. Mostly this attribute
+/// should be used when the set of arguments to a function is described
+/// as part of a macro. The usage is:
+/// \code
+/// void Func(T1 arg1, ARCH_UNUSED_ARG T2 arg2, ARCH_UNUSED_ARG T3 arg3, T4 arg4) {
+/// ...
+/// }
+/// \endcode
+///
+/// \hideinitializer
+# define ARCH_UNUSED_ARG __attribute__ ((unused))
+
+/// Macro used to indicate that a function's code must always be emitted even
+/// if not required.
+///
+/// This attribute is especially useful with templated registration functions,
+/// which might not be present in the linked binary if they are not used (or
+/// the compiler optimizes away their use.)
+///
+/// The usage is:
+/// \code
+/// template
+/// struct TraitsClass {
+/// static void RegistryFunction() ARCH_USED_FUNCTION {
+/// ...
+/// }
+/// };
+/// \endcode
+///
+/// \hideinitializer
+# define ARCH_USED_FUNCTION __attribute__((used))
+
+/// Macro to indicate a function should be executed by the dynamic loader when
+/// the dynamic object (library or program) is loaded.
+///
+/// The priority is used to order the execution of constructors. Valid
+/// values are integers over 100. Constructors with lower numbers are
+/// run first. Constructors for C++ objects at global scope are run
+/// after these functions regardless of priority.
+///
+/// \hideinitializer
+# define ARCH_CONSTRUCTOR_DEFINE(_priority, _name, ...) \
+ __attribute__((constructor(_priority))) \
+ static void _name(__VA_ARGS__)
+
+/// Macro to indicate a function should be executed by the dynamic loader when
+/// the dynamic object (library or program) is unloaded.
+///
+/// The priority is used to order the execution of destructors. Valid
+/// values are integers over 100. Destructors with higher numbers are
+/// run first.
+///
+/// \hideinitializer
+# define ARCH_DESTRUCTOR(_priority, _name, ...) \
+ __attribute__((destructor(_priority))) \
+ static void _name(__VA_ARGS__)
+
+#elif defined(ARCH_COMPILER_MSVC)
+
+#include
+
+ /*!
* \hideinitializer
* \brief Macro used to indicate a function takes a printf-like specification.
*
@@ -50,8 +168,8 @@
* fourth argument is where the var-args corresponding to the format string begin.
*/
# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg) \
- __attribute__((format(printf, _fmt, _firstArg)))
-/*!
+ _Printf_format_string_
+ /*!
* \hideinitializer
* \brief Macro used to indicate a function takes a scanf-like specification.
*
@@ -65,9 +183,9 @@
* format string begin.
*/
# define ARCH_SCANF_FUNCTION(_fmt, _firstArg) \
- __attribute__((format(scanf, _fmt, _firstArg)))
+ _Printf_format_string_
-/*!
+ /*!
* \hideinitializer
* \brief Macro used to indicate that a function should never be inlined
*
@@ -76,9 +194,9 @@
* void Func(T1 arg1, T2 arg2) ARCH_NOINLINE;
* \endcode
*/
-# define ARCH_NOINLINE __attribute__((noinline))
+# define ARCH_NOINLINE // __declspec(noinline)
-/*!
+ /*!
* \hideinitializer
* \brief Macro used to indicate a function parameter may be unused.
*
@@ -91,9 +209,9 @@
* }
* \endcode
*/
-# define ARCH_UNUSED_ARG __attribute__ ((unused))
+# define ARCH_UNUSED_ARG
-/*!
+ /*!
* \brief Macro used to indicate that a function's code must always be emitted
* even if not required.
*
@@ -111,38 +229,29 @@
* };
* \endcode
*/
-# define ARCH_USED_FUNCTION __attribute__((used))
+# define ARCH_USED_FUNCTION
-/*!
- * \brief Macro to indicate a function should be executed by the dynamic
- * loader when the dynamic object (library or program) is loaded.
- *
- * The priority is used to order the execution of constructors. Valid
- * values are integers over 100. Constructors with lower numbers are
- * run first. Constructors for C++ objects at global scope are run
- * after these functions regardless of priority.
+ /*!
+ * \brief Macro to ensure the linker does not strip a symbol.
*/
-# define ARCH_CONSTRUCTOR(_priority) __attribute__((constructor(_priority)))
+# define ARCH_NO_STRIP_SYMBOL(x) __pragma(comment(linker,"/include:__" ## x))
-/*!
- * \brief Macro to indicate a function should be executed by the dynamic
- * loader when the dynamic object (library or program) is unloaded.
- *
- * The priority is used to order the execution of destructors. Valid
- * values are integers over 100. Destructors with higher numbers are
- * run first.
+ /*!
+ * \brief ARCH_CONSTRUCTOR and ARCH_DESTRUCTOR are defined in a separate
+ * file for Windows due to the amount of platform specific code
+ * involved.
*/
-# define ARCH_DESTRUCTOR(_priority) __attribute__((destructor(_priority)))
+#include "pxr/base/arch/attributesWindows.h"
#else
# define ARCH_PRINTF_FUNCTION(_fmt, _firstArg)
# define ARCH_SCANF_FUNCTION(_fmt, _firstArg)
# define ARCH_NOINLINE
# define ARCH_UNUSED_ARG
-/* ARCH_USED_FUNCTION is deliberately omitted. If a new compiler is deployed,
- * we want the build to fail rather than generate executables that will fail
- * at runtime in potentially mysterious ways. Similarly ARCH_CONSTRUCTOR
- * and ARCH_DESTRUCTOR. */
-#endif /* defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) */
+// ARCH_USED_FUNCTION is deliberately omitted. If a new compiler is deployed,
+// we want the build to fail rather than generate executables that will fail
+// at runtime in potentially mysterious ways. Similarly ARCH_CONSTRUCTOR and
+// ARCH_DESTRUCTOR.
+#endif // defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
#endif // ARCH_ATTRIBUTES_H
diff --git a/pxr/base/lib/arch/attributesWindows.h b/pxr/base/lib/arch/attributesWindows.h
new file mode 100644
index 0000000000..fdc111fdf4
--- /dev/null
+++ b/pxr/base/lib/arch/attributesWindows.h
@@ -0,0 +1,125 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#ifndef ARCH_ATTRIBUTES_WINDOWS_H
+#define ARCH_ATTRIBUTES_WINDOWS_H
+
+#pragma section(".pxr$a", read)
+#pragma section(".pxr$c", read)
+#pragma section(".pxr$e", read)
+
+typedef void(__cdecl *Arch_CtorType )(void);
+
+template
+struct Arch_CtorA
+{
+ __declspec(allocate(".pxr$a")) static Arch_CtorType x;
+};
+template Arch_CtorType Arch_CtorA::x;
+
+template
+struct Arch_CtorC
+{
+ __declspec(allocate(".pxr$c")) static Arch_CtorType x;
+};
+template Arch_CtorType Arch_CtorC::x;
+
+template
+struct Arch_CtorE
+{
+ __declspec(allocate(".pxr$e")) static Arch_CtorType x;
+};
+template Arch_CtorType Arch_CtorE::x;
+
+template struct Arch_CtorA;
+template struct Arch_CtorC;
+template struct Arch_CtorE;
+
+#define ARCH_PRIORITY_CAT(section, priority) ARCH_STRINGIFY(section ## priority)
+
+#define ARCH_CONSTRUCTOR_DEFINE(priority, name, ...) \
+ static void name(__VA_ARGS__); \
+ __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \
+ __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \
+ Arch_CtorType tf_ctor_ ## name = (Arch_CtorType )&name; \
+ static void name(__VA_ARGS__)
+
+#define ARCH_CONSTRUCTOR(priority, tag, name) \
+ __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \
+ __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \
+ Arch_CtorType tf_ctor_ ## tag = (Arch_CtorType )&name; \
+
+#define ARCH_DESTRUCTOR(priority, name, ...) \
+ static void name(__VA_ARGS__); \
+ __pragma(section(ARCH_PRIORITY_CAT(.pxr$d, priority), read)) \
+ __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$d, priority))) \
+ Arch_CtorType tf_dtor_ ## name = (Arch_CtorType )&name; \
+ static void name(__VA_ARGS__)
+
+#define ARCH_CONSTRUCTOR_TEMPLATE_DECLARE(priority, name, ...) \
+ __pragma(section(ARCH_PRIORITY_CAT(.pxr$b, priority), read)) \
+ __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$b, priority))) \
+ static Arch_CtorType tf_ctor_ ## name; \
+ static void name(__VA_ARGS__)
+
+#define ARCH_DESTRUCTOR_TEMPLATE_DECLARE(priority, name, ...) \
+ __pragma(section(ARCH_PRIORITY_CAT(.pxr$d, priority), read)) \
+ __declspec(allocate(ARCH_PRIORITY_CAT(.pxr$d, priority))) \
+ static Arch_CtorType tf_dtor_ ## name; \
+ static void name(__VA_ARGS__)
+
+#define ARCH_CONSTRUCTOR_TEMPLATE_DEFINE(priority, scope, name, ...) \
+template <> Arch_CtorType scope::tf_ctor_ ## name = (Arch_CtorType)&scope::name
+
+#define ARCH_DESTRUCTOR_TEMPLATE_DEFINE(priority, scope, name, ...) \
+template <> Arch_CtorType scope::tf_dtor_ ## name = (Arch_CtorType)&scope::name
+
+
+#define archRunConstructors() \
+ { \
+ Arch_CtorType * i = &Arch_CtorA::x; \
+ Arch_CtorType * n = &Arch_CtorC::x; \
+ \
+ while (++i != n) \
+ { \
+ if (*i) \
+ { \
+ (*i)(); \
+ } \
+ } \
+ }
+
+#define archRunDestructors() \
+ { \
+ Arch_CtorType * i = &Arch_CtorE::x; \
+ Arch_CtorType * n = &Arch_CtorC::x; \
+ \
+ while (--i != n) \
+ { \
+ if (*i) \
+ { \
+ (*i)(); \
+ } \
+ } \
+ }
+#endif // ARCH_ATTRIBUTES_WINDOWS_H
diff --git a/pxr/base/lib/arch/buildMode.h b/pxr/base/lib/arch/buildMode.h
index 50ad74cef4..8181188a2f 100644
--- a/pxr/base/lib/arch/buildMode.h
+++ b/pxr/base/lib/arch/buildMode.h
@@ -30,11 +30,6 @@
#error This include file can be included only in C++ programs.
#endif
-/*
- * The various flavor Makefiles are responsible for defining
- * either BUILD_OPTLEVEL_DEV or BUILD_OPTLEVEL_OPT.
- */
-
struct ArchBuildMode {
#if defined(BUILD_OPTLEVEL_DEV)
diff --git a/pxr/base/lib/arch/daemon.cpp b/pxr/base/lib/arch/daemon.cpp
index b523927022..c89b601a64 100644
--- a/pxr/base/lib/arch/daemon.cpp
+++ b/pxr/base/lib/arch/daemon.cpp
@@ -21,6 +21,10 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/defines.h"
+
+#if !defined(ARCH_OS_WINDOWS)
+
#include "pxr/base/arch/daemon.h"
#include
#include
@@ -109,3 +113,5 @@ int ArchCloseAllFiles(int nExcept, const int* exceptFds)
return retStatus;
}
+
+#endif // #if !defined(ARCH_OS_WINDOWS)
\ No newline at end of file
diff --git a/pxr/base/lib/arch/daemon.h b/pxr/base/lib/arch/daemon.h
index 6261de5b98..6dea0c01d0 100644
--- a/pxr/base/lib/arch/daemon.h
+++ b/pxr/base/lib/arch/daemon.h
@@ -24,42 +24,37 @@
#ifndef ARCH_DAEMON_H
#define ARCH_DAEMON_H
-/*!
- * \file daemon.h
- * \brief Create background or daemon processes.
- * \ingroup group_arch_Multithreading
- */
+/// \file arch/daemon.h
+/// \ingroup group_arch_Multithreading
+/// Create background or daemon processes.
-/*!
- * \brief Close all file descriptors (with possible exceptions)
- * \ingroup group_arch_Multithreading
- *
- * \c ArchCloseAllFiles will close all file descriptors open in the
- * current process. Occasionally you'd like to close all files except
- * for some small subset (like 0, 1, and 2). The \p nExcept and \p
- * exceptFds arguments can be used to provide the list of exceptions.
- * \c ArchDaemonizeProcess uses this method to close all unwanted file
- * descriptors in the daemon process.
- *
- * \p nExcept should be the number of elements in the \p exceptFds array.
- * Invalid file descriptors in exceptFds are ignored.
- *
- * \note Be \b very careful when using this routine. It is intended
- * to be used after a \c fork(2) call to close \b all unwanted file
- * descriptors. However, it does not flush stdio buffers, wait for
- * processes opened with popen, shut down the X11 display connection,
- * or anything. It just slams closed all the file descriptors. This
- * is appropriate following a \c fork(2) call as all these file
- * descriptors are duplicates of the ones in the parent process and
- * shutting down the X11 display connection would mess up the parent's
- * X11 display. But you shouldn't use \c ArchCloseAllFiles unless you
- * know what you are doing.
- *
- * \return -1 on error and \c errno will be set to an appropriate
- * value. Returns 0 on success.
- *
- * \sa ArchDaemonizeProcess
- */
+/// Close all file descriptors (with possible exceptions)
+///
+/// \c ArchCloseAllFiles will close all file descriptors open in the
+/// current process. Occasionally you'd like to close all files except
+/// for some small subset (like 0, 1, and 2). The \p nExcept and \p
+/// exceptFds arguments can be used to provide the list of exceptions.
+/// \c ArchDaemonizeProcess uses this method to close all unwanted file
+/// descriptors in the daemon process.
+///
+/// \p nExcept should be the number of elements in the \p exceptFds array.
+/// Invalid file descriptors in exceptFds are ignored.
+///
+/// \note Be \b very careful when using this routine. It is intended
+/// to be used after a \c fork(2) call to close \b all unwanted file
+/// descriptors. However, it does not flush stdio buffers, wait for
+/// processes opened with popen, shut down the X11 display connection,
+/// or anything. It just slams closed all the file descriptors. This
+/// is appropriate following a \c fork(2) call as all these file
+/// descriptors are duplicates of the ones in the parent process and
+/// shutting down the X11 display connection would mess up the parent's
+/// X11 display. But you shouldn't use \c ArchCloseAllFiles unless you
+/// know what you are doing.
+///
+/// \return -1 on error and \c errno will be set to an appropriate
+/// value. Returns 0 on success.
+///
+/// \ingroup group_arch_Multithreading
int ArchCloseAllFiles(int nExcept, const int* exceptFds);
#endif // ARCH_DAEMON_H
diff --git a/pxr/base/lib/arch/debugger.cpp b/pxr/base/lib/arch/debugger.cpp
index 293f688ec2..2f81dfe8c1 100644
--- a/pxr/base/lib/arch/debugger.cpp
+++ b/pxr/base/lib/arch/debugger.cpp
@@ -25,6 +25,7 @@
#include "pxr/base/arch/debugger.h"
#include "pxr/base/arch/daemon.h"
+#include "pxr/base/arch/env.h"
#include "pxr/base/arch/error.h"
#include "pxr/base/arch/export.h"
#include "pxr/base/arch/stackTrace.h"
@@ -44,11 +45,11 @@
#include
#include
#include
-#endif
-#if defined(ARCH_OS_WINDOWS)
+#elif defined(ARCH_OS_WINDOWS)
#include
#include
#endif
+#include
// We don't want this inlined so ArchDebuggerTrap() is as clean as
// possible. The fewer instructions in that function, the more likely
@@ -451,7 +452,7 @@ Arch_InitDebuggerAttach()
// Parse the contents of the ARCH_DEBUGGER environment variable and
// store the result. This way we can avoid using the heap or tricky
// stack allocations when launching the debugger.
- char* e = getenv("ARCH_DEBUGGER");
+ const char* e = ArchGetEnv("ARCH_DEBUGGER");
if (e and e[0]) {
std::string link;
diff --git a/pxr/base/lib/arch/debugger.h b/pxr/base/lib/arch/debugger.h
index 22996813f6..89c90fd13e 100644
--- a/pxr/base/lib/arch/debugger.h
+++ b/pxr/base/lib/arch/debugger.h
@@ -24,11 +24,13 @@
#ifndef ARCH_DEBUGGER_H
#define ARCH_DEBUGGER_H
-/// \file debugger.h
+/// \file arch/debugger.h
+/// Routines for interacting with a debugger.
+#include "pxr/base/arch/api.h"
#include "pxr/base/arch/attributes.h"
-/// \brief Stop in a debugger.
+/// Stop in a debugger.
///
/// This function will do one of the following: start a debugger
/// attached to this process stopped on this function; stop in an
@@ -50,18 +52,20 @@
/// attached terminal by putting the process into the foreground or
/// background.
///
+ARCH_API
void ArchDebuggerTrap() ARCH_NOINLINE;
-/// \brief Cause debug traps to wait for the debugger or not.
+/// Cause debug traps to wait for the debugger or not.
///
/// When \p wait is \c true the next call to \c ArchDebuggerTrap()
/// will cause the process to wait for a signal. The user can attach
/// a debugger to continue the process. The process will not wait
/// again until another call to this function with \p wait \c true.
///
+ARCH_API
void ArchDebuggerWait(bool wait);
-/// \brief Attach a debugger
+/// Attach a debugger.
///
/// Attaches the debugger by running the contents of the enviroment variable
/// ARCH_DEBUGGER using /bin/sh. Any '%p' in the contents of this variable
@@ -70,14 +74,16 @@ void ArchDebuggerWait(bool wait);
///
/// Returns true if ARCH_DEBUGGER is set and the debugger was successfully
/// launched, otherwise returns false.
+ARCH_API
bool ArchDebuggerAttach() ARCH_NOINLINE;
-/// \brief Test if a debugger is attached
+/// Test if a debugger is attached
///
/// Attempts to detect if a debugger is currently attached to the process.
+ARCH_API
bool ArchDebuggerIsAttached() ARCH_NOINLINE;
-/// \brief Stop in the debugger.
+/// Stop in the debugger.
///
/// This macro expands to \c ArchDebuggerTrap() and, if necessary and
/// possible, code to prevent optimization so the caller appears in the
diff --git a/pxr/base/lib/arch/defines.h b/pxr/base/lib/arch/defines.h
index 0fd5b2d0c7..0a4444bc0b 100644
--- a/pxr/base/lib/arch/defines.h
+++ b/pxr/base/lib/arch/defines.h
@@ -24,9 +24,9 @@
#ifndef ARCH_DEFINES_H
#define ARCH_DEFINES_H
-/*
- * OS
- */
+//
+// OS
+//
#if defined(__linux__)
#define ARCH_OS_LINUX
@@ -42,9 +42,9 @@
#define ARCH_OS_WINDOWS
#endif
-/*
- * Processor
- */
+//
+// Processor
+//
#if defined(i386) || defined(__i386__) || defined(__x86_64__) || \
defined(_M_IX86) || defined(_M_X64)
@@ -53,11 +53,9 @@
#define ARCH_CPU_ARM
#endif
-
-
-/*
- * Bits
- */
+//
+// Bits
+//
#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64)
#define ARCH_BITS_64
@@ -65,11 +63,9 @@
#error "Unsupported architecture. x86_64 or ARM64 required."
#endif
-
-
-/*
- * Compiler
- */
+//
+// Compiler
+//
#if defined(__clang__)
#define ARCH_COMPILER_CLANG
@@ -85,14 +81,13 @@
#define ARCH_COMPILER_ICC
#elif defined(_MSC_VER)
#define ARCH_COMPILER_MSVC
-#define ARCH_COMPILER_MSVC_VERSION _MSC_VER
+#define ARCH_COMPILER_MSVC_VERSION _MSC_VER
#endif
+//
+// Features
+//
-
-/*
- * Features
- */
// XXX -- This is an interim solution during the port to C++11. We want to
// use pure C++11 so we don't want to use the __typeof__ extension.
// Once we don't require backward compatibility we can find and fix
@@ -115,6 +110,11 @@
template struct Arch_TypeOfRemoveReference { typedef T type; };
template struct Arch_TypeOfRemoveReference { typedef T type; };
#define ARCH_TYPEOF(x) typename Arch_TypeOfRemoveReference::type
+#elif defined(ARCH_OS_WINDOWS)
+#define ARCH_TYPEOF(x) decltype(x)
+#else
+// This extension is widely supported so fallback to it.
+#define ARCH_TYPEOF __typeof__
#endif
// The current version of Apple clang does not support the thread_local
@@ -128,4 +128,9 @@ template struct Arch_TypeOfRemoveReference { typedef T type; };
#define ARCH_HAS_MMAP_MAP_POPULATE
#endif
+// Some static asserts are not supported due to difference in size types.
+#if defined(ARCH_OS_LINUX)
+ #define ARCH_COMPILER_HAS_STATIC_ASSERT
+#endif
+
#endif // ARCH_DEFINES_H
diff --git a/pxr/base/lib/arch/demangle.cpp b/pxr/base/lib/arch/demangle.cpp
index 38c127bc39..4b821c324e 100644
--- a/pxr/base/lib/arch/demangle.cpp
+++ b/pxr/base/lib/arch/demangle.cpp
@@ -74,6 +74,23 @@ _FixupStringNames(string* name)
while ((pos = name->find("std::", pos)) != string::npos) {
name->erase(pos, 5);
}
+
+#if defined(ARCH_OS_WINDOWS)
+ pos = 0;
+ while ((pos = name->find("class", pos)) != string::npos) {
+ name->erase(pos, 6);
+ }
+
+ pos = 0;
+ while ((pos = name->find("struct", pos)) != string::npos) {
+ name->erase(pos, 7);
+ }
+
+ pos = 0;
+ while ((pos = name->find("enum", pos)) != string::npos) {
+ name->erase(pos, 5);
+ }
+#endif
}
#if defined(ARCH_COMPILER_ICC)
diff --git a/pxr/base/lib/arch/demangle.h b/pxr/base/lib/arch/demangle.h
index 0cd270a4b6..0a7a59c0de 100644
--- a/pxr/base/lib/arch/demangle.h
+++ b/pxr/base/lib/arch/demangle.h
@@ -28,41 +28,35 @@
#error This include file can only be included in C++ programs.
#endif
-/*!
- * \file demangle.h
- * \brief Demangle C++ typenames generated by the \c typeid() facility.
- * \ingroup group_arch_Strings
- */
+/// \file arch/demangle.h
+/// \ingroup group_arch_Strings
+/// Demangle C++ typenames generated by the \c typeid() facility.
+#include "pxr/base/arch/api.h"
#include
#include
#include
+/// \addtogroup group_arch_Strings
+///@{
-/*!
- * \brief Demangle RTTI generated type-name.
- * \ingroup group_arch_Strings
- *
- * Given a variable \c v, the construct \c typeid(v).name() returns
- * the type-name of \c v; unfortunately, the returned type-name is
- * sometimes extremely encoded (otherwise known as "mangled").
- * \c ArchDemangle parses the passed in type-name \c typeName into a
- * readable form, and overwrites \c typeName. If \c typeName
- * cannot be unmangled, the function returns \c false without altering
- * \c typeName. Otherwise \c true is returned.
- */
+/// Demangle RTTI-generated type name.
+///
+/// Given a variable \c v, the construct \c typeid(v).name() returns
+/// the type-name of \c v; unfortunately, the returned type-name is
+/// sometimes extremely encoded (otherwise known as "mangled").
+/// \c ArchDemangle parses the passed in type-name \c typeName into a
+/// readable form, and overwrites \c typeName. If \c typeName
+/// cannot be unmangled, the function returns \c false without altering
+/// \c typeName. Otherwise \c true is returned.
+ARCH_API bool ArchDemangle(std::string* typeName);
-
-bool ArchDemangle(std::string* typeName);
-
-/*!
- * \brief Return demangled RTTI generated-type name.
- * \ingroup group_arch_Strings
- *
- * If \c typeName can be demangled, the function returns the demangled
- * string; otherwise, the function returns the empty string.
- * See \c ArchDemangle() for details.
- */
+/// Return demangled RTTI-generated type name.
+///
+/// If \c typeName can be demangled, the function returns the demangled
+/// string; otherwise, the function returns the empty string.
+///
+/// \see ArchDemangle()
inline std::string
ArchGetDemangled(const std::string& typeName)
{
@@ -72,46 +66,44 @@ ArchGetDemangled(const std::string& typeName)
return std::string();
}
-/*!
- * \brief Return demangled RTTI generated-type name.
- * \ingroup group_arch_Strings
- * \overload
- *
- * Returns the demangled name associated with typeInfo (i.e. typeInfo.name()).
- * See \c ArchDemangle() for details.
- */
+/// Return demangled RTTI-generated type name.
+///
+/// Returns the demangled name associated with typeInfo (i.e. typeInfo.name()).
+///
+/// \see ArchDemangle()
+/// \overload
inline std::string
ArchGetDemangled(const std::type_info& typeInfo) {
return ArchGetDemangled(typeInfo.name());
}
-/*!
- * \brief Return demangled RTTI generated-type name.
- * \ingroup group_arch_Strings
- * \overload
- *
- * Returns the demangled name associated with typeIndex (i.e. typeIndex.name()).
- * See \c ArchDemangle() for details.
- */
+/// Return demangled RTTI-generated type name.
+///
+/// Returns the demangled name associated with typeIndex (i.e. typeIndex.name()).
+///
+/// \see ArchDemangle()
+/// \overload
inline std::string
ArchGetDemangled(const std::type_index& typeIndex) {
return ArchGetDemangled(typeIndex.name());
}
-/*!
- * \brief Return demangled RTTI generated-type name.
- * \ingroup group_arch_Strings
- * \overload
- *
- * Returns the demangled name of type T.
- * See \c ArchDemangle() for details.
- */
+/// Return demangled RTTI generated-type name.
+///
+/// Returns the demangled name of type T.
+///
+/// \see ArchDemangle()
+/// \overload
template
inline std::string
ArchGetDemangled() {
return ArchGetDemangled(typeid(T).name());
}
+///@}
+
+/// \private
+ARCH_API
void Arch_DemangleFunctionName(std::string* functionName);
#endif // ARCH_DEMANGLE_H
diff --git a/pxr/base/lib/arch/env.cpp b/pxr/base/lib/arch/env.cpp
new file mode 100644
index 0000000000..e7a32bd452
--- /dev/null
+++ b/pxr/base/lib/arch/env.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#include "pxr/base/arch/env.h"
+#include "pxr/base/arch/error.h"
+
+const char* ArchGetEnv(const std::string &name)
+{
+#if defined(ARCH_OS_WINDOWS)
+ size_t requiredSize;
+
+ getenv_s(&requiredSize, NULL, 0, name.c_str());
+ if (requiredSize)
+ {
+ static std::string result;
+
+ if (requiredSize < result.size())
+ result.resize(requiredSize);
+
+ getenv_s(&requiredSize, &result[0], requiredSize, name.c_str());
+ return result.c_str();
+ }
+ else
+ return nullptr;
+
+#else
+ return getenv(name.c_str());
+#endif
+}
+
+bool ArchSetEnv(const std::string &name, const std::string &value, int overwrite)
+{
+#if defined(ARCH_OS_WINDOWS)
+ if (_putenv_s(name.c_str(), value.c_str()) == 0)
+#else
+ if (setenv(name.c_str(), value.c_str(), overwrite) == 0)
+#endif
+ return true;
+
+ ARCH_WARNING("Error setting an environment variable");
+ return false;
+}
+
+bool ArchRemoveEnv(const std::string &name)
+{
+#if defined(ARCH_OS_WINDOWS)
+ if (_putenv_s(name.c_str(), nullptr) == 0)
+#else
+ if (unsetenv(name.c_str()) == 0)
+#endif
+ return true;
+
+ return false;
+}
\ No newline at end of file
diff --git a/pxr/base/lib/arch/env.h b/pxr/base/lib/arch/env.h
new file mode 100644
index 0000000000..6d45eb235e
--- /dev/null
+++ b/pxr/base/lib/arch/env.h
@@ -0,0 +1,59 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#ifndef ARCH_ENV_H
+#define ARCH_ENV_H
+
+#include "pxr/base/arch/api.h"
+
+#include
+
+/*!
+ * \file env.h
+ * \brief Architecture dependent access to environment variables.
+ * \ingroup group_arch_SystemFunctions
+ */
+
+
+/*!
+* \brief Gets a value from the current environment identified by \c name.
+* \ingroup group_arch_SystemFunctions
+*/
+ARCH_API
+const char* ArchGetEnv(const std::string &name);
+
+/*!
+ * \brief Creates or modifies an environment variable.
+ * \ingroup group_arch_SystemFunctions
+ */
+ARCH_API
+bool ArchSetEnv(const std::string &name, const std::string &value, int overwrite);
+
+/*!
+* \brief Removes an environment variable.
+* \ingroup group_arch_SystemFunctions
+*/
+ARCH_API
+bool ArchRemoveEnv(const std::string &name);
+
+#endif // ARCH_ENV_H
diff --git a/pxr/base/lib/arch/errno.cpp b/pxr/base/lib/arch/errno.cpp
index 0809135786..c34b6d76ce 100644
--- a/pxr/base/lib/arch/errno.cpp
+++ b/pxr/base/lib/arch/errno.cpp
@@ -21,10 +21,14 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/defines.h"
#include "pxr/base/arch/errno.h"
#include "pxr/base/arch/defines.h"
#include
#include
+#if defined(ARCH_OS_WINDOWS)
+#include
+#endif
std::string
ArchStrerror()
@@ -58,3 +62,31 @@ ArchStrerror(int errorCode)
#endif
return msg_buf;
}
+
+std::string ArchStrSysError(unsigned long errorCode)
+{
+#if defined(ARCH_OS_WINDOWS)
+ if(errorCode == 0)
+ return std::string();
+
+ LPSTR buffer = nullptr;
+ size_t len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr,
+ errorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&buffer,
+ 0,
+ nullptr);
+
+ std::string message(buffer, len);
+
+ OutputDebugString(buffer);
+ LocalFree(buffer);
+
+ return message;
+#else
+ return std::string();
+#endif
+}
\ No newline at end of file
diff --git a/pxr/base/lib/arch/errno.h b/pxr/base/lib/arch/errno.h
index b34c3c3da3..6bef3f4922 100644
--- a/pxr/base/lib/arch/errno.h
+++ b/pxr/base/lib/arch/errno.h
@@ -24,30 +24,35 @@
#ifndef ARCH_ERRNO_H
#define ARCH_ERRNO_H
-/*!
- * \file errno.h
- * \brief Functions for dealing with system errors.
- * \ingroup group_arch_SystemFunctions
- */
+/// \file arch/errno.h
+/// \ingroup group_arch_SystemFunctions
+/// Functions for dealing with system errors.
+#include "pxr/base/arch/api.h"
#include
-/*!
- * \brief Return the error string for the current value of errno.
- * \ingroup group_arch_SystemFunctions
- *
- * This function provides a thread-safe method of fetching the error string
- * from errno. POSIX.1c defines errno as a macro which provides access to a
- * thread-local integer. This function uses strerror_r, which is thread-safe.
- */
-std::string ArchStrerror();
+/// \addtogroup group_arch_SystemFunctions
+///@{
+
+/// Return the error string for the current value of errno.
+///
+/// This function provides a thread-safe method of fetching the error string
+/// from errno. POSIX.1c defines errno as a macro which provides access to a
+/// thread-local integer. This function uses strerror_r, which is thread-safe.
+/// \overload
+ARCH_API std::string ArchStrerror();
+
+/// Return the error string for the specified value of errno.
+///
+/// This function uses strerror_r, which is thread-safe.
+ARCH_API std::string ArchStrerror(int errorCode);
/*!
- * \brief Return the error string for the specified value of errno.
- * \ingroup group_arch_SystemFunctions
- *
- * This function uses strerror_r, which is thread-safe.
- */
-std::string ArchStrerror(int errorCode);
+* \brief Return the error string for the current system error.
+* \ingroup group_arch_SystemFunctions
+*
+* This function uses strerror_r, which is thread-safe.
+*/
+ARCH_API std::string ArchStrSysError(unsigned long errorCode);
#endif // ARCH_ERRNO_H
diff --git a/pxr/base/lib/arch/error.h b/pxr/base/lib/arch/error.h
index ad963ca0c0..a8fb26c36b 100644
--- a/pxr/base/lib/arch/error.h
+++ b/pxr/base/lib/arch/error.h
@@ -24,69 +24,59 @@
#ifndef ARCH_ERROR_H
#define ARCH_ERROR_H
+/// \file arch/error.h
+/// \ingroup group_arch_Diagnostics
+/// Low-level fatal error reporting.
+
#include "pxr/base/arch/defines.h"
+#include "pxr/base/arch/api.h"
#include "pxr/base/arch/functionLite.h"
#include
-/*no!
- * Note: this is an internal (i.e. lib/arch only) header file.
- * Doxygen is off deliberately (until we get \internal working correctly).
- *
- * \file arch/error.h
- * \brief Low-level fatal error reporting.
- * \ingroup group_arch_Diagnostics
- */
-
-/*no!
- * \brief Print message to standard error and abort program.
- * \ingroup group_arch_Diagnostics
- *
- * \param msg The reason for the failure.
- * \param funcName The name of the function that \c Arch_Error was called from.
- * \param lineNo The line number of the file that \c Arch_Error was called from.
- * \param fileName The name of the file that \c Arch_Error was called from.
- *
- * \remark
- * This function is usually called via the ARCH_ERROR macro.
- */
+/// Print message to standard error and abort program.
+///
+/// \param msg The reason for the failure.
+/// \param funcName The name of the function that \c Arch_Error was called from.
+/// \param lineNo The line number of the file that \c Arch_Error was called from.
+/// \param fileName The name of the file that \c Arch_Error was called from.
+///
+/// \private
+ARCH_API
void Arch_Error(const char* msg, const char* funcName,
size_t lineNo, const char* fileName);
-/*no!
- * \brief Print warning message to standard error, but continue execution.
- * \ingroup group_arch_Diagnostics
- *
- * \param msg The reason for the warning.
- * \param funcName The name of the function that \c Arch_Warning was called from.
- * \param lineNo The line number of the file that \c Arch_Warning was called from.
- * \param fileName The name of the file that \c Arch_Warning was called from.
- *
- * \remark
- * This function is usually called via the ARCH_WARNING macro.
- */
+/// Print warning message to standard error, but continue execution.
+///
+/// \param msg The reason for the warning.
+/// \param funcName The name of the function that \c Arch_Warning was called from.
+/// \param lineNo The line number of the file that \c Arch_Warning was called from.
+/// \param fileName The name of the file that \c Arch_Warning was called from.
+///
+/// \private
void Arch_Warning(const char* msg, const char* funcName,
size_t lineNo, const char* fileName);
-/*no!
- * \hideinitializer
- * \brief Unconditionally aborts the program.
- * \ingroup group_arch_Diagnostics
- *
- * \param msg is a literal string, a \c const \c char* (but not
- * an \c std::string) that describes why the program is aborting.
- */
+/// \addtogroup group_arch_Diagnostics
+///@{
+
+/// Unconditionally aborts the program.
+///
+/// \param msg is a literal string, a \c const \c char* (but not
+/// an \c std::string) that describes why the program is aborting.
+/// \hideinitializer
#define ARCH_ERROR(msg) Arch_Error(msg, __ARCH_FUNCTION__, __LINE__, BUILD_COMPONENT_SRC_PREFIX __FILE__)
-/*no!
- * \hideinitializer
- * \brief Prints a warning message to stderr.
- * \ingroup group_arch_Diagnostics
- *
- * \param msg is a literal string, a \c const \c char* (but not
- * an \c std::string).
- */
+/// Prints a warning message to stderr.
+///
+/// \param msg is a literal string, a \c const \c char* (but not
+/// an \c std::string).
+/// \hideinitializer
#define ARCH_WARNING(msg) Arch_Warning(msg, __ARCH_FUNCTION__, __LINE__, BUILD_COMPONENT_SRC_PREFIX __FILE__)
+/// Aborts the program if \p cond evaluates to false.
+/// \hideinitializer
#define ARCH_AXIOM(cond) if (!(cond)) ARCH_ERROR("[" #cond "] axiom failed")
+///@}
+
#endif // ARCH_ERROR_H
diff --git a/pxr/base/lib/arch/export.h b/pxr/base/lib/arch/export.h
index e6c7351c13..021fe9ac5d 100644
--- a/pxr/base/lib/arch/export.h
+++ b/pxr/base/lib/arch/export.h
@@ -24,138 +24,135 @@
#ifndef ARCH_EXPORT_H
#define ARCH_EXPORT_H
-#include "pxr/base/arch/defines.h"
-
-/*!
- * \file export.h
- * \brief Defines symbol visibility macros.
- * \ingroup group_arch_SymbolVisibility
- *
- * Defines \c ARCH_EXPORT to indicate a symbol should be exported from
- * a library, \c ARCH_IMPORT to indicate an exported symbol should be
- * imported (which only matters on Windows), and \c ARCH_HIDDEN to
- * indicate that a symbol which would be exported should not be.
- *
- * The correct way to use these macros is for each library to make a
- * header that looks like this (for some hypothetical library named foo):
- *
- * \code
- * #ifndef FOO_API_H
- * #define FOO_API_H
- *
- * #include "pxr/base/arch/export.h"
- *
- * #if defined(FOO_STATIC)
- * # define FOO_API
- * # define FOO_API_TEMPLATE_CLASS(...)
- * # define FOO_API_TEMPLATE_STRUCT(...)
- * # define FOO_LOCAL
- * #else
- * # if defined(FOO_EXPORTS)
- * # define FOO_API ARCH_EXPORT
- * # define FOO_API_TEMPLATE_CLASS(...)
- * # define FOO_API_TEMPLATE_STRUCT(...)
- * # else
- * # define FOO_API ARCH_IMPORT
- * # define FOO_API_TEMPLATE_CLASS(...) extern template class FOO_API __VA_ARGS__
- * # define FOO_API_TEMPLATE_STRUCT(...) extern template struct FOO_API __VA_ARGS__
- * # endif
- * # define FOO_LOCAL ARCH_HIDDEN
- * #endif
- *
- * #endif
- * \endcode
- *
- * Note that every library has its own unique _API and _LOCAL macros and
- * the expansion of these macros depends on whether the library is being
- * built or used (indicated by the externally set macro FOO_EXPORTS).
- *
- * Library headers then include this header and mark classes, methods,
- * functions and variables as part of the API or local. Each case is
- * described below.
- *
- * A class is added to the API like this:
- *
- * \code
- * class FOO_API FooClass ...
- * \endcode
- *
- * This will add every member to the API, including implicitly created
- * members like a default constructor, default assignment, the vtable
- * and the type_info. The type_info is especially important. If you
- * will dynamic_cast to the type or catch an exception using the type
- * outside of the library, you \b must put its type_info into the API.
- * The only way to do that is to put the whole class into the API.
- *
- * Note that template classes do not get added to the API that way.
- * Instead they are added when explicitly instantiated like so:
- *
- * \code
- * template class FOO_API FooTemplateClass;
- * \endcode
- *
- * It's also sometimes necessary to indicate that an instantiation exists
- * in the API and that a client should not do any of its own instantiation.
- * This is necessary, for example, when the template has static data members
- * and is done by using extern template in the header file that provides the
- * type. Two of the macros above will do that:
- *
- * \code
- * FOO_API_TEMPLATE_CLASS(FooTemplateClass);
- * FOO_API_TEMPLATE_STRUCT(FooTemplateClass);
- * \endcode
- *
- * Which you use depends on if FooTemplateClass is a class or struct. The
- * macro is used because we don't want to always use extern template, but
- * only when we're importing a dynamic library.
- *
- * A template that is completely inlined does not need to be added to the
- * API since it's simply instantiated where needed.
- *
- * Functions, methods and variables can also be put into the API:
- *
- * \code
- * struct FooLocalClass {
- * ~FooLocalClass();
- * FOO_API void MoveTheThing();
- * };
- * FOO_API FooLocalClass* FooNewThing();
- * FOO_API extern int doNotUseGlobalVariables;
- * \endcode
- *
- * Just because FooLocalClass is not in the API doesn't mean clients can't
- * have pointers and references to instances. What they can't do is call
- * member functions not in the API (or, as indicated above, use RTTI for
- * it). So, for example:
- *
- * \code
- * FooLocalClass* thing = FooNewThing();
- * thing->MoveTheThing();
- * (void)dynamic_cast(thing); // Link error!
- * delete thing; // Link error!
- * \endcode
- *
- * Deleting the FooLocalClass instance attempts to use the (non-API) d'tor
- * and fails to link. If we had an implicitly defined d'tor then the
- * deletion would have worked, presuming FooLocalClass didn't have any
- * data members with non-API d'tors.
- *
- * A method of a class added to the API is itself in the API but on some
- * platforms (i.e. not Windows) you can remove it from the API using
- * FOO_LOCAL:
- *
- * \code
- * struct FOO_API FooSemiAPI {
- * void DoSomethingPublic();
- * FOO_LOCAL void _DoSomethingPrivate();
- * };
- * \endcode
- *
- * Clients of the library will fail to link if they use _DoSomethingPrivate()
- * if FOO_LOCAL is supported. If not then the symbol will remain in the API.
- *
- */
+/// \file arch/export.h
+/// \ingroup group_arch_SymbolVisibility
+///
+/// Defines symbol visibility macros.
+///
+/// Defines \c ARCH_EXPORT to indicate a symbol should be exported from
+/// a library, \c ARCH_IMPORT to indicate an exported symbol should be
+/// imported (which only matters on Windows), and \c ARCH_HIDDEN to
+/// indicate that a symbol which would be exported should not be.
+///
+/// The correct way to use these macros is for each library to make a
+/// header that looks like this (for some hypothetical library named foo):
+///
+/// \code
+/// #ifndef FOO_API_H
+/// #define FOO_API_H
+///
+/// #include "pxr/base/arch/export.h"
+///
+/// #if defined(FOO_STATIC)
+/// # define FOO_API
+/// # define FOO_API_TEMPLATE_CLASS(...)
+/// # define FOO_API_TEMPLATE_STRUCT(...)
+/// # define FOO_LOCAL
+/// #else
+/// # if defined(FOO_EXPORTS)
+/// # define FOO_API ARCH_EXPORT
+/// # define FOO_API_TEMPLATE_CLASS(...)
+/// # define FOO_API_TEMPLATE_STRUCT(...)
+/// # else
+/// # define FOO_API ARCH_IMPORT
+/// # define FOO_API_TEMPLATE_CLASS(...) extern template class FOO_API __VA_ARGS__
+/// # define FOO_API_TEMPLATE_STRUCT(...) extern template struct FOO_API __VA_ARGS__
+/// # endif
+/// # define FOO_LOCAL ARCH_HIDDEN
+/// #endif
+///
+/// #endif
+/// \endcode
+///
+/// Note that every library has its own unique _API and _LOCAL macros and
+/// the expansion of these macros depends on whether the library is being
+/// built or used (indicated by the externally set macro FOO_EXPORTS).
+///
+/// Library headers then include this header and mark classes, methods,
+/// functions and variables as part of the API or local. Each case is
+/// described below.
+///
+/// A class is added to the API like this:
+///
+/// \code
+/// class FOO_API FooClass ...
+/// \endcode
+///
+/// This will add every member to the API, including implicitly created
+/// members like a default constructor, default assignment, the vtable
+/// and the type_info. The type_info is especially important. If you
+/// will dynamic_cast to the type or catch an exception using the type
+/// outside of the library, you \b must put its type_info into the API.
+/// The only way to do that is to put the whole class into the API.
+///
+/// Note that template classes do not get added to the API that way.
+/// Instead they are added when explicitly instantiated like so:
+///
+/// \code
+/// template class FOO_API FooTemplateClass;
+/// \endcode
+///
+/// It's also sometimes necessary to indicate that an instantiation exists
+/// in the API and that a client should not do any of its own instantiation.
+/// This is necessary, for example, when the template has static data members
+/// and is done by using extern template in the header file that provides the
+/// type. Two of the macros above will do that:
+///
+/// \code
+/// FOO_API_TEMPLATE_CLASS(FooTemplateClass);
+/// FOO_API_TEMPLATE_STRUCT(FooTemplateClass);
+/// \endcode
+///
+/// Which you use depends on if FooTemplateClass is a class or struct. The
+/// macro is used because we don't want to always use extern template, but
+/// only when we're importing a dynamic library.
+///
+/// A template that is completely inlined does not need to be added to the
+/// API since it's simply instantiated where needed.
+///
+/// Functions, methods and variables can also be put into the API:
+///
+/// \code
+/// struct FooLocalClass {
+/// ~FooLocalClass();
+/// FOO_API void MoveTheThing();
+/// };
+/// FOO_API FooLocalClass* FooNewThing();
+/// FOO_API extern int doNotUseGlobalVariables;
+/// \endcode
+///
+/// Just because FooLocalClass is not in the API doesn't mean clients can't
+/// have pointers and references to instances. What they can't do is call
+/// member functions not in the API (or, as indicated above, use RTTI for
+/// it). So, for example:
+///
+/// \code
+/// FooLocalClass* thing = FooNewThing();
+/// thing->MoveTheThing();
+/// (void)dynamic_cast(thing); // Link error!
+/// delete thing; // Link error!
+/// \endcode
+///
+/// Deleting the FooLocalClass instance attempts to use the (non-API) d'tor
+/// and fails to link. If we had an implicitly defined d'tor then the
+/// deletion would have worked, presuming FooLocalClass didn't have any
+/// data members with non-API d'tors.
+///
+/// A method of a class added to the API is itself in the API but on some
+/// platforms (i.e. not Windows) you can remove it from the API using
+/// FOO_LOCAL:
+///
+/// \code
+/// struct FOO_API FooSemiAPI {
+/// void DoSomethingPublic();
+/// FOO_LOCAL void _DoSomethingPrivate();
+/// };
+/// \endcode
+///
+/// Clients of the library will fail to link if they use _DoSomethingPrivate()
+/// if FOO_LOCAL is supported. If not then the symbol will remain in the API.
+#include "pxr/base/arch/defines.h"
#if defined(ARCH_OS_WINDOWS)
# if defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR >= 4 || defined(ARCH_COMPILER_CLANG)
diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp
index d172da5340..b52dbfa63b 100644
--- a/pxr/base/lib/arch/fileSystem.cpp
+++ b/pxr/base/lib/arch/fileSystem.cpp
@@ -23,41 +23,82 @@
//
#include "pxr/base/arch/fileSystem.h"
#include "pxr/base/arch/defines.h"
+#include "pxr/base/arch/env.h"
#include "pxr/base/arch/error.h"
#include "pxr/base/arch/export.h"
+#include "pxr/base/arch/hints.h"
#include "pxr/base/arch/vsnprintf.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
#include
#include
+#if defined(ARCH_OS_WINDOWS)
+#include
+#include
+#include
+#else
+#include
+#include
#include
+#include
+#endif
#include
#include
#include
-#include
#include
#include
-#include
#include
#include
+#include
+
+#if defined (ARCH_OS_WINDOWS)
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#endif // ARCH_OS_WINDOWS
using std::string;
using std::set;
+#if defined (ARCH_OS_WINDOWS)
+static inline HANDLE _FileToWinHANDLE(FILE *file) {
+ return reinterpret_cast(_get_osfhandle(_fileno(file)));
+}
+#endif // ARCH_OS_WINDOWS
+
+FILE* ArchOpenFile(char const* fileName, char const* mode)
+{
+ FILE* stream = nullptr;
+#if defined(ARCH_OS_WINDOWS)
+ fopen_s(&stream, fileName, mode);
+#else
+ stream = fopen(fileName, mode);
+#endif
+ return stream;
+}
+
+#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
int
ArchGetFilesystemStats(const char *path, struct statfs *buf)
{
-#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
return statfs(path, buf) != -1;
-#else
-#error Unknown system architecture.
-#endif
}
+#endif
int
ArchStatCompare(enum ArchStatComparisonOp op,
const struct stat *stat1,
const struct stat *stat2)
{
-#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
+#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) || defined(ARCH_OS_WINDOWS)
switch (op) {
case ARCH_STAT_MTIME_EQUAL:
return (stat1->st_mtime == stat2->st_mtime);
@@ -88,6 +129,11 @@ ArchStatIsWritable(const struct stat *st)
;
}
return false;
+#elif defined(ARCH_OS_WINDOWS)
+ if (st) {
+ return (st->st_mode & _S_IWRITE) ? true : false;
+ }
+ return false;
#else
#error Unknown system architecture.
#endif
@@ -100,6 +146,9 @@ ArchGetModificationTime(const struct stat& st)
return st.st_mtim.tv_sec + 1e-9*st.st_mtim.tv_nsec;
#elif defined(ARCH_OS_DARWIN)
return st.st_mtimespec.tv_sec + 1e-9*st.st_mtimespec.tv_nsec;
+#elif defined(ARCH_OS_WINDOWS)
+ // NB: this may need adjusting
+ return static_cast(st.st_mtime);
#else
#error Unknown system architecture
#endif
@@ -112,6 +161,9 @@ ArchGetAccessTime(const struct stat& st)
return st.st_atim.tv_sec + 1e-9*st.st_atim.tv_nsec;
#elif defined(ARCH_OS_DARWIN)
return st.st_atimespec.tv_sec + 1e-9*st.st_atimespec.tv_nsec;
+#elif defined(ARCH_OS_WINDOWS)
+ // NB: this may need adjusting
+ return static_cast(st.st_atime);
#else
#error Unknown system architecture
#endif
@@ -124,16 +176,51 @@ ArchGetStatusChangeTime(const struct stat& st)
return st.st_ctim.tv_sec + 1e-9*st.st_ctim.tv_nsec;
#elif defined(ARCH_OS_DARWIN)
return st.st_ctimespec.tv_sec + 1e-9*st.st_ctimespec.tv_nsec;
+#elif defined(ARCH_OS_WINDOWS)
+ // NB: this may need adjusting
+ return static_cast(st.st_mtime);
#else
#error Unknown system architecture
#endif
}
-int
+namespace {
+ struct _Fcloser {
+ inline void operator()(FILE *f) const { if (f) { fclose(f); } }
+ };
+} // anon
+
+using _UniqueFILE = std::unique_ptr;
+
+int64_t
+ArchGetFileLength(FILE *file)
+{
+ if (!file)
+ return -1;
+#if defined (ARCH_OS_LINUX) || defined (ARCH_OS_DARWIN)
+ struct stat buf;
+ return fstat(fileno(file), &buf) < 0 ? -1 :
+ static_cast(buf.st_size);
+#elif defined (ARCH_OS_WINDOWS)
+ LARGE_INTEGER sz;
+ return GetFileSizeEx(_FileToWinHANDLE(file), &sz) ?
+ static_cast(sz.QuadPart) : -1;
+#else
+#error Unknown system architecture
+#endif
+}
+
+int64_t
ArchGetFileLength(const char* fileName)
{
+#if defined (ARCH_OS_LINUX) || defined (ARCH_OS_DARWIN)
struct stat buf;
- return stat(fileName, &buf) < 0 ? -1 : int(buf.st_size);
+ return stat(fileName, &buf) < 0 ? -1 : static_cast(buf.st_size);
+#elif defined (ARCH_OS_WINDOWS)
+ return ArchGetFileLength(_UniqueFILE(ArchOpenFile(fileName, "rb")).get());
+#else
+#error Unknown system architecture
+#endif
}
string
@@ -143,13 +230,18 @@ ArchMakeTmpFileName(const string& prefix, const string& suffix)
static std::atomic nCalls(1);
const int n = nCalls++;
+#if defined(ARCH_OS_WINDOWS)
+ int pid = _getpid();
+#else
+ int pid = getpid();
+#endif
if (n == 1)
return ArchStringPrintf("%s/%s.%d%s", tmpDir.c_str(), prefix.c_str(),
- getpid(), suffix.c_str());
+ pid, suffix.c_str());
else
return ArchStringPrintf("%s/%s.%d.%d%s", tmpDir.c_str(), prefix.c_str(),
- getpid(), n, suffix.c_str());
+ pid, n, suffix.c_str());
}
int
@@ -162,6 +254,41 @@ int
ArchMakeTmpFile(const std::string& tmpdir,
const std::string& prefix, std::string* pathname)
{
+#if defined(ARCH_OS_WINDOWS)
+ char filename[ARCH_PATH_MAX];
+ UINT ret = ::GetTempFileName(tmpdir.c_str(), prefix.c_str(), 0, filename);
+ if (ret == 0)
+ {
+ ARCH_ERROR("Call to GetTempFileName failed.");
+ return -1;
+ }
+
+ // Attempt to create the file
+ HANDLE fileHandle = ::CreateFile(filename,
+ GENERIC_WRITE, // open for write
+ 0, // not for sharing
+ NULL, // default security
+ CREATE_ALWAYS, // overwrite existing
+ FILE_ATTRIBUTE_NORMAL, //normal file
+ NULL); // no template
+
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ ARCH_ERROR("Call to CreateFile failed.");
+ return -1;
+ }
+
+ // Close the file
+ ::CloseHandle(fileHandle);
+
+ if (pathname)
+ {
+ *pathname = filename;
+ }
+
+ int fd = 0;
+ _sopen_s(&fd, filename, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+ return fd;
+#else
// Format the template.
std::string sTemplate =
ArchStringPrintf("%s/%s.XXXXXX", tmpdir.c_str(), prefix.c_str());
@@ -183,24 +310,31 @@ ArchMakeTmpFile(const std::string& tmpdir,
//
fchmod(fd, 0640);
}
-
- return fd;
+ return fd;
+#endif
}
std::string
ArchMakeTmpSubdir(const std::string& tmpdir,
const std::string& prefix)
{
+ std::string retstr;
+
// Format the template.
std::string sTemplate =
ArchStringPrintf("%s/%s.XXXXXX", tmpdir.c_str(), prefix.c_str());
// Copy template to a writable buffer.
char* cTemplate = reinterpret_cast(alloca(sTemplate.size() + 1));
- strcpy(cTemplate, sTemplate.c_str());
-
- std::string retstr;
+#if defined(ARCH_OS_WINDOWS)
+ strcpy_s(cTemplate, sTemplate.size() + 1, sTemplate.c_str());
+ if (::CreateDirectory(sTemplate.c_str(), NULL))
+ {
+ retstr = sTemplate;
+ }
+#else
+ strcpy(cTemplate, sTemplate.size() + 1, sTemplate.c_str());
// Open the tmpdir.
char *tmpSubdir = mkdtemp(cTemplate);
@@ -211,7 +345,7 @@ ArchMakeTmpSubdir(const std::string& tmpdir,
retstr = tmpSubdir;
}
-
+#endif
return retstr;
}
@@ -221,7 +355,22 @@ ARCH_HIDDEN
void
Arch_InitTmpDir()
{
- if (char* tmpdir = getenv("TMPDIR")) {
+#if defined(ARCH_OS_WINDOWS)
+ char tmpPath[MAX_PATH];
+
+ // On Windows, let GetTempPath use the standard env vars, not our own.
+ int sizeOfPath = GetTempPath(MAX_PATH - 1, tmpPath);
+ if (sizeOfPath > MAX_PATH || sizeOfPath == 0) {
+ ARCH_ERROR("Call to GetTempPath failed.");
+ _TmpDir = ".";
+ return;
+ }
+
+ // Strip the trailing slash
+ tmpPath[sizeOfPath-1] = 0;
+ _TmpDir = _strdup(tmpPath);
+#else
+ if (const char* tmpdir = ArchGetEnv("TMPDIR")) {
// This function is not exposed in the header; it is only used during
// Arch_InitConfig. If this is called more than once when TMPDIR is
// set, the following call will leak a string.
@@ -233,6 +382,7 @@ Arch_InitTmpDir()
_TmpDir = "/var/tmp";
#endif
}
+#endif
}
const char *
@@ -284,3 +434,183 @@ ArchGetAutomountDirectories()
return result;
}
+
+
+void
+Arch_Unmapper::operator()(char const *mapStart) const
+{
+ void *ptr = static_cast(const_cast(mapStart));
+ if (!ptr)
+ return;
+#if defined(ARCH_OS_WINDOWS)
+ UnmapViewOfFile(ptr);
+#else // assume POSIX
+ munmap(ptr, _length);
+#endif
+}
+
+void
+Arch_Unmapper::operator()(char *mapStart) const
+{
+ (*this)(static_cast(mapStart));
+}
+
+template
+static inline Mapping
+Arch_MapFileImpl(FILE *file)
+{
+ using PtrType = typename Mapping::pointer;
+ constexpr bool isConst =
+ std::is_const::value;
+
+ auto length = ArchGetFileLength(file);
+ if (length < 0)
+ return Mapping();
+
+#if defined(ARCH_OS_WINDOWS)
+ uint64_t unsignedLength = length;
+ DWORD maxSizeHigh = static_cast(unsignedLength >> 32);
+ DWORD maxSizeLow = static_cast(unsignedLength);
+ HANDLE hFileMap = CreateFileMapping(
+ _FileToWinHANDLE(file), NULL,
+ PAGE_READONLY /* allow read-only or copy-on-write */,
+ maxSizeHigh, maxSizeLow, NULL);
+ if (hFileMap == NULL)
+ return Mapping();
+ auto ptr = static_cast(
+ MapViewOfFile(hFileMap, isConst ? FILE_MAP_READ : FILE_MAP_COPY,
+ /*offsetHigh=*/ 0, /*offsetLow=*/0, unsignedLength));
+ // Close the mapping handle, and return the view pointer.
+ CloseHandle(hFileMap);
+ return Mapping(ptr, Arch_Unmapper());
+#else // Assume POSIX
+ return Mapping(
+ static_cast(
+ mmap(nullptr, length, isConst ? PROT_READ : PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fileno(file), 0)), Arch_Unmapper(length));
+#endif
+}
+
+ArchConstFileMapping
+ArchMapFileReadOnly(FILE *file)
+{
+ return Arch_MapFileImpl(file);
+}
+
+ArchMutableFileMapping
+ArchMapFileReadWrite(FILE *file)
+{
+ return Arch_MapFileImpl(file);
+}
+
+int64_t
+ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset)
+{
+ if (count == 0)
+ return 0;
+
+#if defined(ARCH_OS_WINDOWS)
+ HANDLE hFile = _FileToWinHANDLE(file);
+
+ OVERLAPPED overlapped;
+ memset(&overlapped, 0, sizeof(overlapped));
+
+ uint64_t uoffset = offset;
+ overlapped.OffsetHigh = static_cast(uoffset >> 32);
+ overlapped.Offset = static_cast(uoffset);
+
+ DWORD numRead = 0;
+ if (ReadFile(hFile, buffer, static_cast(count),
+ &numRead, &overlapped)) {
+ return numRead;
+ }
+ return -1;
+#else // assume POSIX
+ // Read and check if all got read (most common case).
+ int fd = fileno(file);
+ // Convert to signed so we can compare the result of pread with count
+ // without the compiler complaining. This conversion is implementation
+ // defined if count is larger than what's representable by int64_t, and
+ // POSIX pread also specifies that this case is implementation defined. We
+ // follow suit.
+ int64_t signedCount = static_cast(count);
+ int64_t nread = pread(fd, buffer, signedCount, offset);
+ if (ARCH_LIKELY(nread == signedCount or nread == 0))
+ return nread;
+
+ // Track a total and retry until we read everything or hit EOF or an error.
+ int64_t total = std::max(nread, 0);
+ while (nread != -1 || (nread == -1 && errno == EINTR)) {
+ // Update bookkeeping and retry.
+ if (nread > 0) {
+ total += nread;
+ signedCount -= nread;
+ offset += nread;
+ buffer = static_cast(buffer) + nread;
+ }
+ nread = pread(fd, buffer, signedCount, offset);
+ if (ARCH_LIKELY(nread == signedCount or nread == 0))
+ return total + nread;
+ }
+
+ // Error case.
+ return -1;
+#endif
+}
+
+int64_t
+ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset)
+{
+ if (offset < 0)
+ return -1;
+
+#if defined(ARCH_OS_WINDOWS)
+ HANDLE hFile = _FileToWinHANDLE(file);
+
+ OVERLAPPED overlapped;
+ memset(&overlapped, 0, sizeof(overlapped));
+
+ uint64_t uoffset = offset;
+ overlapped.OffsetHigh = static_cast(uoffset >> 32);
+ overlapped.Offset = static_cast(uoffset);
+
+ DWORD numWritten = 0;
+ if (WriteFile(hFile, bytes, static_cast(count),
+ &numWritten, &overlapped)) {
+ return numWritten;
+ }
+ return -1;
+#else // assume POSIX
+ // It's claimed that correct, modern POSIX will never return 0 for (p)write
+ // unless count is zero. It will either be the case that some bytes were
+ // written, or we get an error return.
+
+ // Write and check if all got written (most common case).
+ int fd = fileno(file);
+ // Convert to signed so we can compare the result of pwrite with count
+ // without the compiler complaining. This conversion is implementation
+ // defined if count is larger than what's representable by int64_t, and
+ // POSIX pwrite also specifies that this case is implementation defined. We
+ // follow suit.
+ int64_t signedCount = static_cast(count);
+ int64_t nwritten = pwrite(fd, bytes, signedCount, offset);
+ if (ARCH_LIKELY(nwritten == signedCount))
+ return nwritten;
+
+ // Track a total and retry until we write everything or hit an error.
+ int64_t total = std::max(nwritten, 0);
+ while (nwritten != -1) {
+ // Update bookkeeping and retry.
+ total += nwritten;
+ signedCount -= nwritten;
+ offset += nwritten;
+ bytes = static_cast(bytes) + nwritten;
+ nwritten = pwrite(fd, bytes, signedCount, offset);
+ if (ARCH_LIKELY(nwritten == signedCount))
+ return total + nwritten;
+ }
+
+ // Error case.
+ return -1;
+#endif
+}
diff --git a/pxr/base/lib/arch/fileSystem.h b/pxr/base/lib/arch/fileSystem.h
index 9569f5da9f..c2c58e3a50 100644
--- a/pxr/base/lib/arch/fileSystem.h
+++ b/pxr/base/lib/arch/fileSystem.h
@@ -24,17 +24,69 @@
#ifndef ARCH_FILESYSTEM_H
#define ARCH_FILESYSTEM_H
+/// \file arch/fileSystem.h
+/// \ingroup group_arch_SystemFunctions
+/// Architecture dependent file system access
+
#include "pxr/base/arch/defines.h"
-#include
-#include
-#include
+#include "pxr/base/arch/api.h"
+#include "pxr/base/arch/inttypes.h"
+#include
+#include
#include
#include
+#include
+#include
+#include
+
#if defined(ARCH_OS_LINUX)
#include
+#include
#elif defined(ARCH_OS_DARWIN)
#include
+#include
+#elif defined(ARCH_OS_WINDOWS)
+#include
+#include
+#endif
+
+/// \addtogroup group_arch_SystemFunctions
+///@{
+#if !defined(ARCH_OS_WINDOWS)
+ #ifdef _POSIX_VERSION
+ #include /* for PATH_MAX */
+ #else
+ #include /* for MAXPATHLEN */
+ #endif
+#endif
+
+#if !defined(ARCH_OS_WINDOWS)
+ #define ARCH_GLOB_DEFAULT GLOB_NOCHECK|GLOB_MARK
+#else
+ #define ARCH_GLOB_DEFAULT 0
+#endif
+
+#ifndef ARCH_PATH_MAX
+ #ifdef _POSIX_VERSION
+ #define ARCH_PATH_MAX _POSIX_PATH_MAX
+ #else
+ #ifdef MAXPATHLEN
+ #define ARCH_PATH_MAX MAXPATHLEN
+ #else
+ #ifdef _MAX_PATH
+ #define ARCH_PATH_MAX _MAX_PATH
+ #else
+ #define ARCH_PATH_MAX 1024
+ #endif
+ #endif
+ #endif
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+ #define ARCH_PATH_SEP ";"
+#else
+ #define ARCH_PATH_SEP ":"
#endif
/*!
@@ -43,6 +95,12 @@
* \ingroup group_arch_SystemFunctions
*/
+/// Return the length of a file in bytes.
+///
+/// Returns -1 if the file cannot be opened/read.
+ARCH_API int64_t ArchGetFileLength(const char *fileName);
+ARCH_API int64_t ArchGetFileLength(FILE *file);
+
/*!
* \brief This enum is used to specify a comparison operator for
* \c ArchStatCompare().
@@ -55,6 +113,54 @@ enum ArchStatComparisonOp {
ARCH_STAT_SAME_FILE /*!< Both refer to same file */
};
+
+/*!
+* \brief Opens a file.
+* \ingroup group_arch_SystemFunctions
+*
+* Opens the file that is specified by filename.
+* Returning true if the file was opened successfully; false otherwise.
+*/
+
+ARCH_API FILE*
+ArchOpenFile(char const* fileName, char const* mode);
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchCloseFile(fd) _close(fd)
+#else
+# define ArchCloseFile(fd) close(fd)
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchUnlinkFile(path) _unlink(path)
+#else
+# define ArchUnlinkFile(path) unlink(path)
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchFileAccess(path, mode) _access(path, mode)
+#else
+# define ArchFileAccess(path, mode) access(path, mode)
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchFdOpen(fd, mode) _fdopen(fd, mode)
+#else
+# define ArchFdOpen(fd, mode) open(fd, mode)
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchFileNo(stream) _fileno(stream)
+#else
+# define ArchFileNo(stream) fileno(stream)
+#endif
+
+#if defined(ARCH_OS_WINDOWS)
+# define ArchFileIsaTTY(stream) _isatty(stream)
+#else
+# define ArchFileIsaTTY(stream) isatty(stream)
+#endif
+
/*!
* \brief Compares two \c stat structures.
* \ingroup group_arch_SystemFunctions
@@ -63,7 +169,7 @@ enum ArchStatComparisonOp {
* operation, returning non-zero if the operation is true with respect
* to \p stat1 and \p stat2.
*/
-
+ARCH_API
int ArchStatCompare(enum ArchStatComparisonOp op,
const struct stat *stat1,
const struct stat *stat2);
@@ -74,125 +180,155 @@ int ArchStatCompare(enum ArchStatComparisonOp op,
*
* Returns -1 if the file cannot be opened/read.
*/
-int ArchGetFileLength(const char* fileName);
-
-/*!
- * \brief Returns true if the data in \c stat struct \p st indicates that the
- * target file or directory is writable.
- *
- * This returns true if the struct pointer is valid, and the stat indicates
- * the target is writable by the effective user, effective group, or all
- * users.
- */
-bool ArchStatIsWritable(const struct stat *st);
+ARCH_API int64_t ArchGetFileLength(const char* fileName);
+ARCH_API int64_t ArchGetFileLength(FILE *file);
-/*!
- * \brief Returns the modification time (mtime) in seconds from the stat struct.
- * \ingroup group_arch_SystemFunctions
- *
- * This function returns the modification time with as much precision as is
- * available in the stat structure for the current platform.
- */
-double ArchGetModificationTime(const struct stat& st);
+/// Returns true if the data in \c stat struct \p st indicates that the target
+/// file or directory is writable.
+///
+/// This returns true if the struct pointer is valid, and the stat indicates
+/// the target is writable by the effective user, effective group, or all
+/// users.
+ARCH_API bool ArchStatIsWritable(const struct stat *st);
-/*!
- * \brief Returns the access time (atime) in seconds from the stat struct.
- * \ingroup group_arch_SystemFunctions
- *
- * This function returns the access time with as much precision as is
- * available in the stat structure for the current platform.
- */
-double ArchGetAccessTime(const struct stat& st);
+/// Returns the modification time (mtime) in seconds from the stat struct.
+///
+/// This function returns the modification time with as much precision as is
+/// available in the stat structure for the current platform.
+ARCH_API double ArchGetModificationTime(const struct stat& st);
-/*!
- * \brief Returns the status change time (ctime) in seconds from the stat struct.
- * \ingroup group_arch_SystemFunctions
- *
- * This function returns the status change time with as much precision as is
- * available in the stat structure for the current platform.
- */
-double ArchGetStatusChangeTime(const struct stat& st);
+/// Returns the access time (atime) in seconds from the stat struct.
+///
+/// This function returns the access time with as much precision as is
+/// available in the stat structure for the current platform.
+ARCH_API double ArchGetAccessTime(const struct stat& st);
-/*!
- * \brief Return the path to a temporary directory for this platform.
- *
- * The returned temporary directory will be a location that will normally
- * be cleaned out on a reboot. This is /var/tmp on Linux machines (for
- * legacy reasons), but /tmp on Darwin machines (/var/tmp on Darwin is
- * specified as a location where files are kept between system reboots -
- * see "man hier"). The returned string will not have a trailing slash.
- * This routine is threadsafe and will not perform any memory allocations.
- *
- */
-const char *ArchGetTmpDir();
+/// Returns the status change time (ctime) in seconds from the stat struct.
+///
+/// This function returns the status change time with as much precision as is
+/// available in the stat structure for the current platform.
+ARCH_API double ArchGetStatusChangeTime(const struct stat& st);
-/*!
- * \brief Make a temporary file name, in a system-determined
- * temporary directory.
- *
- * The result returned has the form TMPDIR/prefix.pid[.n]suffix
- * where TMPDIR is a system-determined temporary directory (typically
- * /tmp or /usr/tmp), pid is the process id of the process, and
- * the optional .n records the number of times this function has been called
- * by a process (and is ommited the first time this function is called).
- *
- * The call is threadsafe.
- *
- * This call opens a security hole because of the race between choosing
- * the name and opening the file. This call should be avoided in favor
- * of ArchMakeTmpFile().
- */
+/// Return the path to a temporary directory for this platform.
+///
+/// The returned temporary directory will be a location that will normally
+/// be cleaned out on a reboot. This is /var/tmp on Linux machines (for
+/// legacy reasons), but /tmp on Darwin machines (/var/tmp on Darwin is
+/// specified as a location where files are kept between system reboots -
+/// see "man hier"). The returned string will not have a trailing slash.
+///
+/// This routine is threadsafe and will not perform any memory allocations.
+ARCH_API const char *ArchGetTmpDir();
+/// Make a temporary file name, in a system-determined temporary directory.
+///
+/// The result returned has the form TMPDIR/prefix.pid[.n]suffix where TMPDIR
+/// is a system-determined temporary directory (typically /tmp or /usr/tmp),
+/// pid is the process id of the process, and the optional .n records the
+/// number of times this function has been called by a process (and is ommited
+/// the first time this function is called).
+///
+/// The call is threadsafe.
+///
+/// \warning This call opens a security hole because of the race between
+/// choosing the name and opening the file. This call should be avoided in
+/// favor of \c ArchMakeTmpFile().
+ARCH_API
std::string ArchMakeTmpFileName(const std::string& prefix,
const std::string& suffix = std::string());
-/*!
- * \brief Create a temporary file, in a system-determined
- * temporary directory.
- *
- * The result returned has the form TMPDIR/prefix.XXXXXX where
- * TMPDIR is a system-determined temporary directory (typically
- * /tmp or /usr/tmp) and XXXXXX is a unique suffix. Returns the
- * file descriptor of the new file and, if pathname isn't NULL,
- * returns the full path to the file in pathname. Returns -1 on
- * failure and errno is set.
- *
- * The call is threadsafe.
- */
+/// Create a temporary file, in a system-determined temporary directory.
+///
+/// The result returned has the form TMPDIR/prefix.XXXXXX where TMPDIR is a
+/// system-determined temporary directory (typically /tmp or /usr/tmp) and
+/// XXXXXX is a unique suffix. Returns the file descriptor of the new file
+/// and, if pathname isn't NULL, returns the full path to the file in
+/// pathname. Returns -1 on failure and errno is set.
+///
+/// The call is threadsafe.
+ARCH_API
int ArchMakeTmpFile(const std::string& prefix, std::string* pathname = 0);
-/*!
- * \brief Create a temporary file, in a given temporary directory.
- *
- * The result returned has the form TMPDIR/prefix.XXXXXX where
- * TMPDIR is the given temporary directory and XXXXXX is a unique
- * suffix. Returns the file descriptor of the new file and, if
- * pathname isn't NULL, returns the full path to the file in
- * pathname. Returns -1 on failure and errno is set.
- *
- * The call is threadsafe.
- */
+/// Create a temporary file, in a given temporary directory.
+///
+/// The result returned has the form TMPDIR/prefix.XXXXXX where TMPDIR is the
+/// given temporary directory and XXXXXX is a unique suffix. Returns the file
+/// descriptor of the new file and, if pathname isn't NULL, returns the full
+/// path to the file in pathname. Returns -1 on failure and errno is set.
+///
+/// The call is threadsafe.
+ARCH_API
int ArchMakeTmpFile(const std::string& tmpdir,
const std::string& prefix, std::string* pathname = 0);
-/*!
- * \brief Create a temporary sub-direcrory, in a given temporary directory.
- *
- * The result returned has the form TMPDIR/prefix.XXXXXX/ where
- * TMPDIR is the given temporary directory and XXXXXX is a unique
- * suffix. Returns the the full path to the subdir in
- * pathname. Returns empty string on failure and errno is set.
- *
- * The call is threadsafe.
- */
+/// Create a temporary sub-direcrory, in a given temporary directory.
+///
+/// The result returned has the form TMPDIR/prefix.XXXXXX/ where TMPDIR is the
+/// given temporary directory and XXXXXX is a unique suffix. Returns the the
+/// full path to the subdir in pathname. Returns empty string on failure and
+/// errno is set.
+///
+/// The call is threadsafe.
+ARCH_API
std::string ArchMakeTmpSubdir(const std::string& tmpdir,
const std::string& prefix);
-/*!
- * \brief Return all automounted directories.
- *
- * Returns a set of all directories that are automount points for the host.
- */
+/// Return all automounted directories.
+///
+/// Returns a set of all directories that are automount points for the host.
+ARCH_API
std::set ArchGetAutomountDirectories();
+// Helper 'deleter' for use with std::unique_ptr for file mappings.
+#if defined(ARCH_OS_WINDOWS)
+struct Arch_Unmapper {
+ ARCH_API void operator()(char *mapStart) const;
+ ARCH_API void operator()(char const *mapStart) const;
+};
+#else // assume POSIX
+struct Arch_Unmapper {
+ Arch_Unmapper() : _length(~0) {}
+ explicit Arch_Unmapper(size_t length) : _length(length) {}
+ ARCH_API void operator()(char *mapStart) const;
+ ARCH_API void operator()(char const *mapStart) const;
+private:
+ size_t _length;
+};
+#endif
+
+/// ArchConstFileMapping and ArchMutableFileMapping are std::unique_ptr and std::unique_ptr respectively. The functions
+/// ArchMapFileReadOnly() and ArchMapFileReadWrite() return them and provide
+/// access to memory-mapped file contents.
+using ArchConstFileMapping = std::unique_ptr;
+using ArchMutableFileMapping = std::unique_ptr;
+
+/// Privately map the passed \p file into memory and return a unique_ptr to the
+/// read-only mapped contents. The contents may not be modified.
+ARCH_API
+ArchConstFileMapping ArchMapFileReadOnly(FILE *file);
+
+/// Privately map the passed \p file into memory and return a unique_ptr to the
+/// copy-on-write mapped contents. If modified, the affected pages are
+/// dissociated from the underlying file and become backed by the system's swap
+/// or page-file storage. Edits are not carried through to the underlying file.
+ARCH_API
+ArchMutableFileMapping ArchMapFileReadWrite(FILE *file);
+
+/// Read up to \p count bytes from \p offset in \p file into \p buffer. The
+/// file position indicator for \p file is not changed. Return the number of
+/// bytes read, or zero if at end of file. Return -1 in case of an error, with
+/// errno set appropriately.
+ARCH_API
+int64_t ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset);
+
+/// Write up to \p count bytes from \p buffer to \p file at \p offset. The file
+/// position indicator for \p file is not changed. Return the number of bytes
+/// written, possibly zero if none written. Return -1 in case of an error, with
+/// errno set appropriately.
+ARCH_API
+int64_t ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset);
+
+///@}
+
#endif // ARCH_FILESYSTEM_H
diff --git a/pxr/base/lib/arch/function.h b/pxr/base/lib/arch/function.h
index 472618d040..d2b7fc4663 100644
--- a/pxr/base/lib/arch/function.h
+++ b/pxr/base/lib/arch/function.h
@@ -24,27 +24,25 @@
#ifndef ARCH_FUNCTION_H
#define ARCH_FUNCTION_H
-/*!
- * \file arch/function.h
- * \brief Define preprocessor fuction name macros.
- *
- * This file extents the functionality of pxr/base/arch/functionLite.h.
- * This file needs to be public but shouldn't be accessed directly by
- * anyone other than lib/tf.
- */
+/// \file arch/function.h
+/// Define preprocessor function name macros.
+///
+/// This file extents the functionality of pxr/base/arch/functionLite.h.
+/// This file needs to be public but shouldn't be included directly by
+/// anything outside of \c lib/tf.
+#include "pxr/base/arch/api.h"
#include "pxr/base/arch/functionLite.h"
-
#include
-/*!
- * \brief Return well formatted function name.
- * \ingroup group_arch_Diagnostic
- *
- * This function assumes \c function is __ARCH_FUNCTION__ and
- * \c prettyFunction is __ARCH_PRETTY_FUNCTION__, and attempts to
- * reconstruct a well formatted function name.
- */
+/// Return well formatted function name.
+///
+/// This function assumes \c function is __ARCH_FUNCTION__ and
+/// \c prettyFunction is __ARCH_PRETTY_FUNCTION__, and attempts to
+/// reconstruct a well formatted function name.
+///
+/// \ingroup group_arch_Diagnostic
+ARCH_API
std::string ArchGetPrettierFunctionName(const std::string &function,
const std::string &prettyFunction);
diff --git a/pxr/base/lib/arch/functionLite.h b/pxr/base/lib/arch/functionLite.h
index 3b9e828493..ea898e0e0a 100644
--- a/pxr/base/lib/arch/functionLite.h
+++ b/pxr/base/lib/arch/functionLite.h
@@ -24,19 +24,16 @@
#ifndef ARCH_FUNCTIONLITE_H
#define ARCH_FUNCTIONLITE_H
-#include "pxr/base/arch/defines.h"
+/// \file arch/functionLite.h
+/// Define preprocessor function name macros.
+///
+/// This file defines preprocessor macros for getting the current function
+/// name so they can be used in a architecture independent matter. This file
+/// needs to be public but shouldn't be included directly by anything outside
+/// of \c pxr/base/tf.
-/*
- * \file functionLite.h
- * \brief Define preprocessor fuction name macros.
- *
- * This file defines preprocessor macros for getting the current function
- * name so they can be used in a architecture independent matter. This file
- * needs to be public but shouldn't be accessed directly by anyone other
- * than lib/tf.
- *
- * Note: this file specifically does not include .
- */
+#include "pxr/base/arch/defines.h"
+// Note: this file specifically does not include .
#if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_ICC) || \
defined(ARCH_COMPILER_CLANG)
diff --git a/pxr/base/lib/arch/hash.cpp b/pxr/base/lib/arch/hash.cpp
index 4c695e6184..cf5e6f0e77 100644
--- a/pxr/base/lib/arch/hash.cpp
+++ b/pxr/base/lib/arch/hash.cpp
@@ -475,7 +475,7 @@ void SpookyHash::Hash128(
remainder = (length - ((const uint8 *)end-(const uint8 *)message));
memcpy(buf, end, remainder);
memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder);
- ((uint8 *)buf)[sc_blockSize-1] = remainder;
+ ((uint8 *)buf)[sc_blockSize-1] = static_cast(remainder);
// do some final mixing
End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
diff --git a/pxr/base/lib/arch/hash.h b/pxr/base/lib/arch/hash.h
index a7f54196f3..653749ceef 100644
--- a/pxr/base/lib/arch/hash.h
+++ b/pxr/base/lib/arch/hash.h
@@ -24,9 +24,12 @@
#ifndef ARCH_HASH_H
#define ARCH_HASH_H
+/// \file arch/hash.h
+/// Hash functions.
+
#include "pxr/base/arch/inttypes.h"
+#include "pxr/base/arch/api.h"
-///
/// Hash \a len bytes of \a data.
///
/// To compute a hash value for data that is not contiguous in memory, iterate
@@ -34,10 +37,19 @@
/// passing it on as \p seed. Note that this is *not* equivalent to hashing the
/// contiguous pieces as a whole. Support for that may be added in future.
///
-uint32_t ArchHash(const char *data, size_t len);
-uint32_t ArchHash(const char *data, size_t len, uint32_t seed);
+ARCH_API uint32_t ArchHash(const char *data, size_t len);
+/// \overload
+ARCH_API uint32_t ArchHash(const char *data, size_t len, uint32_t seed);
-uint64_t ArchHash64(const char *data, size_t len);
-uint64_t ArchHash64(const char *data, size_t len, uint64_t seed);
+/// Hash \a len bytes of \a data.
+///
+/// To compute a hash value for data that is not contiguous in memory, iterate
+/// over all the contiguous blocks of memory and accumulate the hash value by
+/// passing it on as \p seed. Note that this is *not* equivalent to hashing the
+/// contiguous pieces as a whole. Support for that may be added in future.
+///
+ARCH_API uint64_t ArchHash64(const char *data, size_t len);
+/// \overload
+ARCH_API uint64_t ArchHash64(const char *data, size_t len, uint64_t seed);
#endif // ARCH_HASH_H
diff --git a/pxr/base/lib/arch/hints.h b/pxr/base/lib/arch/hints.h
index 6588fecd1e..de6625d75e 100644
--- a/pxr/base/lib/arch/hints.h
+++ b/pxr/base/lib/arch/hints.h
@@ -26,12 +26,15 @@
#include "pxr/base/arch/defines.h"
-// ARCH_LIKELY(bool-expr) and ARCH_UNLIKELY(bool-expr) will evaluate to the
-// value of bool-expr but will also emit compiler intrinsics providing hints for
-// branch prediction if the compiler has such intrinsics. It is advised that
-// you only use these in cases where you empirically know the outcome of
-// bool-expr to a very high degree of certainty. For example, fatal-error
-// cases, invariants, first-time initializations, etc.
+/// \file arch/hints.h
+/// Compiler hints.
+///
+/// \c ARCH_LIKELY(bool-expr) and \c ARCH_UNLIKELY(bool-expr) will evaluate to
+/// the value of bool-expr but will also emit compiler intrinsics providing
+/// hints for branch prediction if the compiler has such intrinsics. It is
+/// advised that you only use these in cases where you empirically know the
+/// outcome of bool-expr to a very high degree of certainty. For example,
+/// fatal-error cases, invariants, first-time initializations, etc.
#if defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG)
diff --git a/pxr/base/lib/arch/initConfig.cpp b/pxr/base/lib/arch/initConfig.cpp
index 9fa0febd77..48a9dad563 100644
--- a/pxr/base/lib/arch/initConfig.cpp
+++ b/pxr/base/lib/arch/initConfig.cpp
@@ -33,10 +33,7 @@ void Arch_InitTickTimer();
namespace {
-ARCH_CONSTRUCTOR(102)
-static
-void
-Arch_InitConfig()
+ARCH_CONSTRUCTOR_DEFINE(102, Arch_InitConfig)
{
// Initialize the application start time. First so it's a close as
// possible to the real start time.
@@ -66,4 +63,4 @@ Arch_InitConfig()
Arch_InitDebuggerAttach();
}
-}
+}
\ No newline at end of file
diff --git a/pxr/base/lib/arch/inttypes.h b/pxr/base/lib/arch/inttypes.h
index 5852d906b4..982defa786 100644
--- a/pxr/base/lib/arch/inttypes.h
+++ b/pxr/base/lib/arch/inttypes.h
@@ -24,21 +24,19 @@
#ifndef ARCH_INTTYPES_H
#define ARCH_INTTYPES_H
+/// \file arch/inttypes.h
+/// \ingroup group_arch_Bits
+/// Define integral types.
+///
+/// By including this file, the "standard" integer types \c int16_t,
+/// \c int32_t, and \c int64_t are all defined, as are their unsigned
+/// counterparts \c uint16_t, \c uint32_t, and \c uint64_t.
+
#include "pxr/base/arch/defines.h"
#include
#include
#include
-/*!
- * \file inttypes.h
- * \brief Define integral types.
- * \ingroup group_arch_Bits
- *
- * By including this file, the "standard" integer types \c int16_t,
- * \c int32_t, and \c int64_t are all defined, as are their unsigned
- * counterparts \c uint16_t, \c uint32_t, and \c uint64_t.
- */
-
typedef unsigned char uchar;
#endif // ARCH_INTTYPES_H
diff --git a/pxr/base/lib/arch/library.cpp b/pxr/base/lib/arch/library.cpp
new file mode 100644
index 0000000000..36cd7f4b92
--- /dev/null
+++ b/pxr/base/lib/arch/library.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#include "pxr/base/arch/library.h"
+
+#if defined(ARCH_OS_WINDOWS)
+#include
+#else
+#include
+#endif
+
+void* ArchOpenLibrary(const std::string &filename, int flag)
+{
+#if defined(ARCH_OS_WINDOWS)
+ return LoadLibrary(filename.c_str());
+#else
+ return dlopen(filename.c_str(), flag);
+#endif
+}
+
+const char* ArchLibraryError()
+{
+#if defined(ARCH_OS_WINDOWS)
+ return 0;
+#else
+ return dlerror();
+#endif
+}
+
+int ArchLibraryClose(void* handle)
+{
+#if defined(ARCH_OS_WINDOWS)
+ int status = ::FreeLibrary(reinterpret_cast(handle));
+#else
+ int status = dlclose(handle);
+#endif
+ return status;
+}
\ No newline at end of file
diff --git a/pxr/base/lib/arch/library.h b/pxr/base/lib/arch/library.h
new file mode 100644
index 0000000000..d62aaf7905
--- /dev/null
+++ b/pxr/base/lib/arch/library.h
@@ -0,0 +1,73 @@
+//
+// Copyright 2016 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+#ifndef ARCH_LIBRARY_H
+#define ARCH_LIBRARY_H
+
+#include "pxr/base/arch/api.h"
+
+#include
+
+#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
+# define ARCH_LIBRARY_LAZY RTLD_LAZY
+# define ARCH_LIBRARY_NOW RTLD_NOW
+# define ARCH_LIBRARY_LOCAL RTLD_LOCAL
+# define ARCH_LIBRARY_GLOBAL RTLD_GLOBAL
+#else
+# define ARCH_LIBRARY_LAZY 0
+# define ARCH_LIBRARY_NOW 0
+# define ARCH_LIBRARY_LOCAL 0
+# define ARCH_LIBRARY_GLOBAL 0
+#endif
+
+/*!
+ * \file library.h
+ * \brief Architecture dependent loading and unloading of dynamic libraries.
+ * \ingroup group_arch_SystemFunctions
+ */
+
+/*!
+* \brief Load an execuctable object file.
+* \ingroup group_arch_SystemFunctions
+*
+* Opens the dynamic library that is specified by filename.
+* Returning the handle to the module if successful; false otherwise.
+*/
+ARCH_API
+void* ArchOpenLibrary(const std::string &filename, int flag);
+
+/*!
+* \brief Obtain a description of the most recent error that occurred from \c ArchOpenLibrary.
+* \ingroup group_arch_SystemFunctions
+*/
+ARCH_API
+const char* ArchLibraryError();
+
+/*!
+ * \brief Closes an object opened with \c ArchOpenLibrary.
+ * \ingroup group_arch_SystemFunctions
+ */
+ARCH_API
+int ArchLibraryClose(void* handle);
+
+#endif // ARCH_LIBRARY_H
diff --git a/pxr/base/lib/arch/mallocHook.cpp b/pxr/base/lib/arch/mallocHook.cpp
index 7e107531ba..5b89bb794a 100644
--- a/pxr/base/lib/arch/mallocHook.cpp
+++ b/pxr/base/lib/arch/mallocHook.cpp
@@ -21,22 +21,26 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
-#include "pxr/base/arch/mallocHook.h"
#include "pxr/base/arch/defines.h"
+#include "pxr/base/arch/env.h"
+#include "pxr/base/arch/mallocHook.h"
#include "pxr/base/arch/attributes.h"
+#include "pxr/base/arch/env.h"
+#if !defined(ARCH_OS_WINDOWS)
#include
+#endif
#include
+#include
#if defined(ARCH_OS_DARWIN)
-#include
+# include
#else
-#include
-#endif /* defined(ARCH_OS_DARWIN) */
-
+# include
#if not defined(__MALLOC_HOOK_VOLATILE)
#define __MALLOC_HOOK_VOLATILE
-#endif /* not defined(__MALLOC_HOOK_VOLATILE) */
+#endif /* not defined __MALLOC_HOOK_VOLATILE */
+#endif /* defined(ARCH_OS_LINUX) */
using std::string;
@@ -81,6 +85,7 @@ static bool
_MallocProvidedBySameLibraryAs(const char* functionName,
bool skipMallocCheck)
{
+#if !defined(ARCH_OS_WINDOWS)
const void* function = dlsym(RTLD_DEFAULT, functionName);
if (!function) {
return false;
@@ -93,6 +98,9 @@ _MallocProvidedBySameLibraryAs(const char* functionName,
}
return (skipMallocCheck || mallocInfo.dli_fbase == functionInfo.dli_fbase);
+#else
+ return false;
+#endif
}
static inline bool
@@ -107,7 +115,7 @@ _CheckMallocTagImpl(const char* impl, const char* libname)
bool
ArchIsPxmallocActive()
{
- const char* impl = getenv("TF_MALLOC_TAG_IMPL");
+ const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL");
if (!_CheckMallocTagImpl(impl, "pxmalloc")) {
return false;
}
@@ -118,7 +126,7 @@ ArchIsPxmallocActive()
bool
ArchIsPtmallocActive()
{
- const char* impl = getenv("TF_MALLOC_TAG_IMPL");
+ const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL");
if (!_CheckMallocTagImpl(impl, "ptmalloc")) {
return false;
}
@@ -129,7 +137,7 @@ ArchIsPtmallocActive()
bool
ArchIsJemallocActive()
{
- const char* impl = getenv("TF_MALLOC_TAG_IMPL");
+ const char* impl = ArchGetEnv("TF_MALLOC_TAG_IMPL");
if (!_CheckMallocTagImpl(impl, "jemalloc")) {
return false;
}
@@ -152,7 +160,7 @@ ArchIsStlAllocatorOff()
* isn't, it's just a preference, not behavior that has to correct
* to avoid a crash.
*/
- static bool isOff = bool(getenv("GLIBCXX_FORCE_NEW"));
+ static bool isOff = bool(ArchGetEnv("GLIBCXX_FORCE_NEW"));
return isOff;
#else
return false;
diff --git a/pxr/base/lib/arch/mallocHook.h b/pxr/base/lib/arch/mallocHook.h
index e5932f7fbc..0ee7011042 100644
--- a/pxr/base/lib/arch/mallocHook.h
+++ b/pxr/base/lib/arch/mallocHook.h
@@ -24,131 +24,126 @@
#ifndef ARCH_MALLOCHOOK_H
#define ARCH_MALLOCHOOK_H
+/// \file arch/mallocHook.h
+/// \ingroup group_arch_Memory
+/// Routines for controlling malloc behavior.
+
+#include "pxr/base/arch/api.h"
#include
#include
-/*!
- * \file mallocHook.h
- * \ingroup group_arch_Memory
- */
-
-/*!
- * \brief Return true if ptmalloc is being used as the memory allocator
- *
- * ptmalloc3 is an external shared library providing implementations of the
- * standard memory allocation functions (e.g. malloc, free). Consumers with
- * special behavior that depends on this library may use this function to
- * determine if it is the active allocator.
- */
-bool ArchIsPtmallocActive();
+/// Return true if ptmalloc is being used as the memory allocator
+///
+/// ptmalloc3 is an external shared library providing implementations of the
+/// standard memory allocation functions (e.g. malloc, free). Consumers with
+/// special behavior that depends on this library may use this function to
+/// determine if it is the active allocator.
+///
+/// \ingroup group_arch_Memory
+ARCH_API bool ArchIsPtmallocActive();
-/*!
- * \brief Return true if the C++ STL allocator was requested
- * to be turned off.
- *
- * Under gcc, this is done by setting the environment variable GLIBCXX_FORCE_NEW,
- * but it might differ (or not even be possible) for other platforms.
- */
+/// Return true if the C++ STL allocator was requested to be turned off.
+///
+/// Under gcc, this is done by setting the environment variable
+/// GLIBCXX_FORCE_NEW, but it might differ (or not even be possible) for other
+/// platforms.
+///
+/// \ingroup group_arch_Memory
bool ArchIsStlAllocatorOff();
-/*!
- * \class ArchMallocHook mallocHook.h pxr/base/arch/mallocHook.h
- * \ingroup group_arch_Memory
- * \brief Override default malloc() functionality.
- *
- * The \c ArchMallocHook class is used on supported systems to install
- * a call-back function in place of the standard malloc/realloc/free/memalign
- * function calls. Supported systems are currently restricted to 64-bit linux systems.
- *
- * The call-back function can access the original allocation function by calling,
- * for example, \c ArchMallocHook::Malloc, or it is free to perform its own allocation.
- *
- * The \c ArchMallocHook is a POD (plain old datastructure) which means that to use
- * it properly, it should be declared at global scope, ensuring zero-initialization.
- */
+/// \class ArchMallocHook
+/// \ingroup group_arch_Memory
+///
+/// Override default malloc() functionality.
+///
+/// The \c ArchMallocHook class is used on supported systems to install a
+/// call-back function in place of the standard malloc/realloc/free/memalign
+/// function calls. Supported systems are currently restricted to 64-bit linux
+/// systems.
+///
+/// The call-back function can access the original allocation function by
+/// calling, for example, \c ArchMallocHook::Malloc, or it is free to perform
+/// its own allocation.
+///
+/// The \c ArchMallocHook is a POD (plain old datastructure) which means that
+/// to use it properly, it should be declared at global scope, ensuring
+/// zero-initialization.
class ArchMallocHook {
public:
- /*!
- * \brief Initialize hooks.
- *
- * Calling \c Initialize() installs the supplied functions as call-back
- * in place of the standard system memory allocation routines. Note that
- * the callbacks take an extra \c const \c void* parameter; on supported systems,
- * the called function should simply ignore the extra parameter.
- *
- * If initialization fails, \c false is returned and \p *errMsg is set accordingly.
- * If \c *this has already been initialized, calling \c Initialize() a second
- * time will fail.
- */
+ /// Initialize hooks.
+ ///
+ /// Calling \c Initialize() installs the supplied functions as call-back
+ /// in place of the standard system memory allocation routines. Note
+ /// that the callbacks take an extra \c const \c void* parameter; on
+ /// supported systems, the called function should simply ignore the extra
+ /// parameter.
+ ///
+ /// If initialization fails, \c false is returned and \p *errMsg is set
+ /// accordingly. If \c *this has already been initialized, calling \c
+ /// Initialize() a second time will fail.
+ ARCH_API
bool Initialize(void* (*mallocWrapper)(size_t, const void*),
- void* (*reallocWrapper)(void*, size_t, const void*),
- void* (*memalignWrapper)(size_t, size_t, const void*),
- void (*freeWrapper)(void*, const void*),
- std::string* errMsg);
-
- /*!
- * \brief Return true if \c *this has been (successfully) initialized.
- *
- * In order for this function to work properly, \c *this cannot be a local
- * or dynamically initialized variable; rather, \c *this must be a global
- * variable, to ensure zero-initialization.
- */
+ void* (*reallocWrapper)(void*, size_t, const void*),
+ void* (*memalignWrapper)(size_t, size_t, const void*),
+ void (*freeWrapper)(void*, const void*),
+ std::string* errMsg);
+
+ /// Return true if \c *this has been (successfully) initialized.
+ ///
+ /// In order for this function to work properly, \c this cannot be a local
+ /// or dynamically initialized variable; rather, \c this must be a global
+ /// variable, to ensure zero-initialization.
+ ARCH_API
bool IsInitialized();
-
- /*!
- * \brief Call the original system \c malloc() function.
- *
- * This function allows user-supplied callbacks to access the original
- * system-supplied malloc() call. For speed reasons, no safety checks
- * are performed; in particular, calling this function without having
- * successfully initialized \p *this will likely crash your program.
- */
+
+ /// Call the original system \c malloc() function.
+ ///
+ /// This function allows user-supplied callbacks to access the original
+ /// system-supplied malloc() call. For speed reasons, no safety checks
+ /// are performed; in particular, calling this function without having
+ /// successfully initialized \p *this will likely crash your program.
+ ARCH_API
void* Malloc(size_t nBytes) {
- return (*_underlyingMallocFunc)(nBytes);
+ return (*_underlyingMallocFunc)(nBytes);
}
-
- /*!
- * \brief Call the original system \c realloc() function.
- *
- * This function allows user-supplied callbacks to access the original
- * system-supplied \c realloc() call. For speed reasons, no safety checks
- * are performed; in particular, calling this function without having
- * successfully initialized \p *this will likely crash your program.
- */
+
+ /// Call the original system \c realloc() function.
+ ///
+ /// This function allows user-supplied callbacks to access the original
+ /// system-supplied \c realloc() call. For speed reasons, no safety checks
+ /// are performed; in particular, calling this function without having
+ /// successfully initialized \p *this will likely crash your program.
+ ARCH_API
void* Realloc(void* ptr, size_t nBytes) {
- return (*_underlyingReallocFunc)(ptr, nBytes);
+ return (*_underlyingReallocFunc)(ptr, nBytes);
}
- /*!
- * \brief Call the original system \c memalign() function.
- *
- * This function allows user-supplied callbacks to access the original
- * system-supplied \c memalign() call. For speed reasons, no safety checks
- * are performed; in particular, calling this function without having
- * successfully initialized \p *this will likely crash your program.
- */
+ /// Call the original system \c memalign() function.
+ ///
+ /// This function allows user-supplied callbacks to access the original
+ /// system-supplied \c memalign() call. For speed reasons, no safety checks
+ /// are performed; in particular, calling this function without having
+ /// successfully initialized \p *this will likely crash your program.
+ ARCH_API
void* Memalign(size_t alignment, size_t nBytes) {
- return (*_underlyingMemalignFunc)(alignment, nBytes);
+ return (*_underlyingMemalignFunc)(alignment, nBytes);
}
- /*!
- * \brief Call the original system \c free() function.
- *
- * This function allows user-supplied callbacks to access the original
- * system-supplied \c free() call. For speed reasons, no safety checks
- * are performed; in particular, calling this function without having
- * successfully initialized \p *this will likely crash your program.
- */
+ /// Call the original system \c free() function.
+ ///
+ /// This function allows user-supplied callbacks to access the original
+ /// system-supplied \c free() call. For speed reasons, no safety checks
+ /// are performed; in particular, calling this function without having
+ /// successfully initialized \p *this will likely crash your program.
+ ARCH_API
void Free(void* ptr) {
- (*_underlyingFreeFunc)(ptr);
+ (*_underlyingFreeFunc)(ptr);
}
private:
- /*
- * Note: this is a POD (plain 'ol data structure)
- * so we depend on zero initialization here to null these
- * out. Do not add a constructor or destructor to this class.
- */
+ // Note: this is a POD (plain 'ol data structure) so we depend on zero
+ // initialization here to null these out. Do not add a constructor or
+ // destructor to this class.
void* (*_underlyingMallocFunc)(size_t);
void* (*_underlyingReallocFunc)(void*, size_t);
diff --git a/pxr/base/lib/arch/math.h b/pxr/base/lib/arch/math.h
index fbd73e69d6..33cd12cc3c 100644
--- a/pxr/base/lib/arch/math.h
+++ b/pxr/base/lib/arch/math.h
@@ -24,45 +24,36 @@
#ifndef ARCH_MATH_H
#define ARCH_MATH_H
-/*!
- * \file math.h
- * \brief Architecture-specific math function calls.
- * \ingroup group_arch_Math
- */
+/// \file arch/math.h
+/// \ingroup group_arch_Math
+/// Architecture-specific math function calls.
#include "pxr/base/arch/defines.h"
#include "pxr/base/arch/inttypes.h"
-#include
#include
#if defined(ARCH_OS_WINDOWS)
+#define _USE_MATH_DEFINES // For M_PI
#include
+#include
#endif
-/*!
- * \brief This is the smallest value e such that 1+e^2 == 1, using floats.
- * \ingroup group_arch_Math
- */
+/// \addtogroup group_arch_Math
+///@{
#if defined (ARCH_CPU_INTEL) || defined(doxygen)
-/*
- * True for all IEEE754 chipsets.
- */
+
+/// This is the smallest value e such that 1+e^2 == 1, using floats.
+/// True for all IEEE754 chipsets.
#define ARCH_MIN_FLOAT_EPS_SQR 0.000244141F
-/*!
- * \brief Three-valued sign. Return 1 if val > 0, 0 if val == 0, or -1 if val <
- * 0;
- */
+/// Three-valued sign. Return 1 if val > 0, 0 if val == 0, or -1 if val < 0.
inline long ArchSign(long val) {
return (val > 0) - (val < 0);
}
-/*!
- * \brief Returns The IEEE-754 bit pattern of the specified single precision
- * value as a 32-bit unsigned integer.
- * \ingroup group_arch_Math
- */
+/// Returns The IEEE-754 bit pattern of the specified single precision value
+/// as a 32-bit unsigned integer.
inline uint32_t ArchFloatToBitPattern(float v) {
union {
float _float;
@@ -72,11 +63,8 @@ inline uint32_t ArchFloatToBitPattern(float v) {
return value._uint;
}
-/*!
- * \brief Returns The single precision floating point value corresponding to
- * the given IEEE-754 bit pattern.
- * \ingroup group_arch_Math
- */
+/// Returns The single precision floating point value corresponding to the
+/// given IEEE-754 bit pattern.
inline float ArchBitPatternToFloat(uint32_t v) {
union {
uint32_t _uint;
@@ -86,11 +74,8 @@ inline float ArchBitPatternToFloat(uint32_t v) {
return value._float;
}
-/*!
- * \brief Returns The IEEE-754 bit pattern of the specified double precision
- * value as a 64-bit unsigned integer.
- * \ingroup group_arch_Math
- */
+/// Returns The IEEE-754 bit pattern of the specified double precision value
+/// as a 64-bit unsigned integer.
inline uint64_t ArchDoubleToBitPattern(double v) {
union {
double _double;
@@ -100,11 +85,8 @@ inline uint64_t ArchDoubleToBitPattern(double v) {
return value._uint;
}
-/*!
- * \brief Returns The double precision floating point value corresponding to
- * the given IEEE-754 bit pattern.
- * \ingroup group_arch_Math
- */
+/// Returns The double precision floating point value corresponding to the
+/// given IEEE-754 bit pattern.
inline double ArchBitPatternToDouble(uint64_t v) {
union {
uint64_t _uint;
@@ -118,24 +100,17 @@ inline double ArchBitPatternToDouble(uint64_t v) {
#error Unknown system architecture.
#endif
-
-/*
- * A bunch of math functions operating on floats.
- */
-
#if defined(ARCH_OS_LINUX) || defined(doxygen)
-/*!
- * \brief Computes the sine and cosine of the specified value as a float.
- * \ingroup group_arch_Math
- */
-inline void ArchSinCosf(float v, float *s, float *c) { sincosf(v, s, c); }
+/// Computes the sine and cosine of the specified value as a float.
+inline void ArchSinCosf(float v, float *s, float *c) {
+ sincosf(v, s, c);
+}
-/*!
- * \brief Computes the sine and cosine of the specified value as a double.
- * \ingroup group_arch_Math
- */
-inline void ArchSinCos(double v, double *s, double *c) { sincos(v, s, c); }
+/// Computes the sine and cosine of the specified value as a double.
+inline void ArchSinCos(double v, double *s, double *c) {
+ sincos(v, s, c);
+}
#elif defined(ARCH_OS_DARWIN) || defined(ARCH_OS_WINDOWS)
@@ -152,4 +127,6 @@ inline void ArchSinCos(double v, double *s, double *c) {
#error Unknown architecture.
#endif
+///@}
+
#endif // ARCH_MATH_H
diff --git a/pxr/base/lib/arch/nap.h b/pxr/base/lib/arch/nap.h
index 871210bcde..e1ac7f404e 100644
--- a/pxr/base/lib/arch/nap.h
+++ b/pxr/base/lib/arch/nap.h
@@ -24,50 +24,40 @@
#ifndef ARCH_NAP_H
#define ARCH_NAP_H
+/// \file arch/nap.h
+/// \ingroup group_arch_Multithreading
+/// Routines for very brief pauses in execution.
+
#include "pxr/base/arch/inttypes.h"
+#include "pxr/base/arch/api.h"
+
#if defined(ARCH_OS_WINDOWS)
-#include
+#include
#endif
-/*!
- * \file nap.h
- * \brief Routines for very brief pauses in execution.
- * \ingroup group_arch_Multithreading
- */
-
-/*!
- * \brief Sleep for some number of centiseconds.
- * \ingroup group_arch_Multithreading
- *
- * Sleep for \c n/100 seconds. Note: if your intent is to simply
- * yield the processors, DO NOT call this with a value of zero (as one
- * can do with sginap()). Call \c ArchThreadYield() instead.
- */
-
-void ArchNap(size_t nhundredths);
+/// \addtogroup group_arch_Multithreading
+///@{
+/// Sleep for some number of centiseconds.
+///
+/// Sleep for \c n/100 seconds. Note: if your intent is to simply yield the
+/// processors, DO NOT call this with a value of zero (as one can do with
+/// sginap()). Call \c ArchThreadYield() instead.
+ARCH_API void ArchNap(size_t nhundredths);
-/*!
- * \brief Yield to the operating system thread scheduler.
- * \ingroup group_arch_Multithreading
- *
- * Returns control to the operating system thread scheduler as a means of
- * temporarily suspending the calling thread.
- */
-
+/// Yield to the operating system thread scheduler.
+///
+/// Returns control to the operating system thread scheduler as a means of
+/// temporarily suspending the calling thread.
+ARCH_API
void ArchThreadYield();
-
-/*!
- * \brief Pause execution of the current thread.
- * \ingroup group_arch_Multithreading
- *
- * Pause execution of the current thread without returning control to the
- * operating system scheduler. This function can be used as a means of
- * gracefully spin waiting while potentially yielding CPU resouces to
- * hyper-threads.
- */
-
+/// Pause execution of the current thread.
+///
+/// Pause execution of the current thread without returning control to the
+/// operating system scheduler. This function can be used as a means of
+/// gracefully spin waiting while potentially yielding CPU resouces to
+/// hyper-threads.
inline void ArchThreadPause() {
#if defined (ARCH_CPU_INTEL) && defined(ARCH_COMPILER_GCC)
__asm__ __volatile__ ("pause");
@@ -78,4 +68,6 @@ inline void ArchThreadPause() {
#endif
}
+///@}
+
#endif // ARCH_NAP_H
diff --git a/pxr/base/lib/arch/overview.dox b/pxr/base/lib/arch/overview.dox
index 9c7e560e2f..3879afa608 100644
--- a/pxr/base/lib/arch/overview.dox
+++ b/pxr/base/lib/arch/overview.dox
@@ -3,34 +3,38 @@
// IF YOU ADD A NEW GROUP, PLEASE ADD IT TO THE LIST BELOW!!
-//! \defgroup group_arch_Bits Bits
-// Functions having to do with how bits are laid out on a machine.
+/// \defgroup group_arch_Bits Bits
+/// Functions having to do with how bits are laid out on a machine.
-//! \defgroup group_arch_Multithreading Multithreading
-// Functions having to do with multithreading.
+/// \defgroup group_arch_Multithreading Multithreading
+/// Functions having to do with multithreading.
-//! \defgroup group_arch_Math Math
-// Functions for math.
+/// \defgroup group_arch_Math Math
+/// Functions for math.
-//! \defgroup group_arch_Strings Strings
-// Functions having to do with string massaging/manipulation
+/// \defgroup group_arch_Strings Strings
+/// Functions having to do with string massaging/manipulation
-//! \defgroup group_arch_SystemFunctions System Functions
-// Functions that encapsulate differing low-level system calls.
+/// \defgroup group_arch_SystemFunctions System Functions
+/// Functions that encapsulate differing low-level system calls.
-//! \defgroup group_arch_Memory Memory Management
-// Functions having to do with memory allocation/handling.
-
-//! \defgroup group_arch_Diagnostics Diagnostics
-// Functions having to do with error reporting/handling.
-
-//! \defgroup group_arch_SymbolVisibility Symbol Visibility
-// Macros having to do with symbol visibility
+/// \defgroup group_arch_Memory Memory Management
+/// Functions having to do with memory allocation/handling.
+/// \defgroup group_arch_Diagnostics Diagnostics
+/// Functions having to do with error reporting/handling.
+/// \defgroup group_arch_SymbolVisibility Symbol Visibility
+/// Macros having to do with symbol visibility
/*!
-\mainpage
+\page arch_page_front Arch: Architecture Dependent
+\if ( PIXAR_MFB_BUILD )
+\mainpage Arch: Architecture Dependent
+\publicLib
+\endif
+
+\section arch_overview Overview
The ARCH library is a repository for all architecture-dependent
code. It isolates all platform dependencies (and confusing \#ifdefs)
diff --git a/pxr/base/lib/arch/pragmas.h b/pxr/base/lib/arch/pragmas.h
index a32062a3b5..59e2598486 100644
--- a/pxr/base/lib/arch/pragmas.h
+++ b/pxr/base/lib/arch/pragmas.h
@@ -24,31 +24,122 @@
#ifndef ARCH_PRAGMAS_H
#define ARCH_PRAGMAS_H
-#include "pxr/base/arch/defines.h"
-
-///
/// \file arch/pragmas.h
-/// \brief Pragmas for controlling compiler-specific behaviors.
-
+/// Pragmas for controlling compiler-specific behaviors.
+///
/// This header contains pragmas used to control compiler-specific behaviors.
/// Behaviors that are not supported or required by a certain compiler should
/// be implemented as a no-op.
-///
+
+#include "pxr/base/arch/defines.h"
#if defined(ARCH_COMPILER_GCC)
+#define ARCH_PRAGMA_PUSH \
+ _Pragma("GCC diagnostic push");
+
+#define ARCH_PRAGMA_RESTORE \
+ _Pragma("GCC diagnostic pop");
+
/// Convert errors about variables that may be used before initialization into
/// warnings. A warning is emitted, but won't cause a build failure with
/// -Werror enabled.
#define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED \
- _Pragma("GCC diagnostic push"); \
+ ARCH_PRAGMA_PUSH \
_Pragma("GCC diagnostic warning \"-Wmaybe-uninitialized\"");
-#define ARCH_PRAGMA_POP_NOERROR_MAYBE_UNINITIALIZED \
- _Pragma("GCC diagnostic pop");
-#else
-#define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED
-#define ARCH_PRAGMA_POP_NOERROR_MAYBE_UNINITIALIZED
+#define ARCH_PRAGMA_MACRO_REDEFINITION
+ ARCH_PRAGMA_PUSH \
+ _Pragma("GCC diagnostic warning \"-Wno-builtin-macro-redefined\"");
+
+#elif defined(ARCH_COMPILER_MSVC)
+
+#define ARCH_PRAGMA_PUSH \
+ __pragma(warning(push))
+
+#define ARCH_PRAGMA_RESTORE \
+ __pragma(warning(pop))
+
+#define ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4003))
+
+#define ARCH_PRAGMA_MACRO_REDEFINITION \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4005))
+
+#define ARCH_PRAGMA_QUALIFIER_HAS_NO_MEANING \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4180))
+
+#define ARCH_PRAGMA_ZERO_SIZED_STRUCT \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4200))
+
+#define ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4251))
+
+#define ARCH_PRAGMA_CONVERSION_FROM_SIZET \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4267))
+
+#define ARCH_PRAGMA_MAY_NOT_BE_ALIGNED \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4316))
+
+#define ARCH_PRAGMA_SHIFT_TO_64_BITS \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4334))
+
+#define ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4624))
+
+#define ARCH_PRAGMA_DEPRECATED_POSIX_NAME \
+ ARCH_PRAGMA_PUSH \
+ __pragma(warning(disable:4996))
+
+#endif
+
+#if !defined ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS
+#define ARCH_PRAGMA_MACRO_TOO_FEW_ARGUMENTS
+#endif
+
+#if !defined ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED
+#define ARCH_PRAGMA_PUSH_NOERROR_MAYBE_UNINITIALIZED
+#endif
+
+#if !defined ARCH_PRAGMA_MACRO_REDEFINITION
+#define ARCH_PRAGMA_MACRO_REDEFINITION
+#endif
+
+#if !defined ARCH_PRAGMA_ZERO_SIZED_STRUCT
+#define ARCH_PRAGMA_ZERO_SIZED_STRUCT
+#endif
+
+#if !defined ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE
+#define ARCH_PRAGMA_NEEDS_EXPORT_INTERFACE
+#endif
+
+#if !defined ARCH_PRAGMA_CONVERSION_FROM_SIZET
+#define ARCH_PRAGMA_CONVERSION_FROM_SIZET
+#endif
+
+#if !defined ARCH_PRAGMA_MAY_NOT_BE_ALIGNED
+#define ARCH_PRAGMA_MAY_NOT_BE_ALIGNED
+#endif
+
+#if !defined ARCH_PRAGMA_SHIFT_TO_64_BITS
+#define ARCH_PRAGMA_SHIFT_TO_64_BITS
+#endif
+
+#if !defined ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE
+#define ARCH_PRAGMA_DESTRUCTOR_IMPLICIT_DEFINE
+#endif
+
+#if !defined ARCH_PRAGMA_DEPRECATED_POSIX_NAME
+#define ARCH_PRAGMA_DEPRECATED_POSIX_NAME
#endif
-#endif // ARCH_PRAGMAS_H
+#endif /* ARCH_PRAGMAS_H */
diff --git a/pxr/base/lib/arch/stackTrace.cpp b/pxr/base/lib/arch/stackTrace.cpp
index f945366220..8529b0d450 100644
--- a/pxr/base/lib/arch/stackTrace.cpp
+++ b/pxr/base/lib/arch/stackTrace.cpp
@@ -21,12 +21,29 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/defines.h"
+#if defined(ARCH_OS_WINDOWS)
+#include
+#include
+#include
+#include
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+#else
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#endif
#include "pxr/base/arch/stackTrace.h"
#include "pxr/base/arch/debugger.h"
-#include "pxr/base/arch/defines.h"
#include "pxr/base/arch/demangle.h"
#include "pxr/base/arch/error.h"
-#include "pxr/base/arch/export.h"
#include "pxr/base/arch/fileSystem.h"
#include "pxr/base/arch/inttypes.h"
#include "pxr/base/arch/symbols.h"
@@ -35,20 +52,13 @@
#include
#include
#include
-#include
-#include
#include
-#include
-#include
-#include
#include
#include
-#include
-#include
#include
-#include
#include
#include
+#include
/* Darwin/ppc did not do stack traces. Darwin/i386 still
needs some work, this has been stubbed out for now. */
@@ -81,6 +91,8 @@ ForkFunc Arch_nonLockingFork =
(ForkFunc)dlsym(RTLD_NEXT, "__libc_fork");
#elif defined(ARCH_OS_DARWIN)
fork; /* XXX -- this is not necessarily correct */
+#elif defined(ARCH_OS_WINDOWS)
+ NULL;
#else
#error Unknown architecture.
#endif
@@ -117,31 +129,20 @@ static Arch_ProgInfoMap _progInfoMap;
// traverse it during an error.
static char *_progInfoForErrors = NULL;
// Mutex for above:
-static pthread_mutex_t _progInfoForErrorsMutex = PTHREAD_MUTEX_INITIALIZER;
+static std::mutex _progInfoForErrorsMutex;
// Key-value map for extra log info. Stores unowned pointers to text to be
// emitted in stack trace logs in case of fatal errors or crashes.
typedef std::map Arch_LogInfoMap;
static Arch_LogInfoMap _logInfoForErrors;
// Mutex for above:
-static pthread_mutex_t _logInfoForErrorsMutex = PTHREAD_MUTEX_INITIALIZER;
-
-namespace {
-// Private auto lock/unlock RAII class for pthread_mutex_t.
-struct Locker {
- explicit Locker(pthread_mutex_t &mutex)
- : _mutex(&mutex) { pthread_mutex_lock(_mutex); }
- ~Locker() { pthread_mutex_unlock(_mutex); }
-private:
- pthread_mutex_t *_mutex;
-};
-}
+static std::mutex _logInfoForErrorsMutex;
static void
_EmitAnyExtraLogInfo(FILE* outFile)
{
// This function can't cause any heap allocation, be careful.
- Locker lock(_logInfoForErrorsMutex);
+ std::lock_guard lock(_logInfoForErrorsMutex);
for (Arch_LogInfoMap::const_iterator i = _logInfoForErrors.begin(),
end = _logInfoForErrors.end(); i != end; ++i) {
fprintf(outFile, "\n%s:\n%s", i->first.c_str(), i->second);
@@ -153,7 +154,7 @@ _EmitAnyExtraLogInfo(FILE* outFile, size_t max)
{
size_t n = 0;
// This function can't cause any heap allocation, be careful.
- Locker lock(_logInfoForErrorsMutex);
+ std::lock_guard lock(_logInfoForErrorsMutex);
for (Arch_LogInfoMap::const_iterator i = _logInfoForErrors.begin(),
end = _logInfoForErrors.end(); i != end; ++i) {
// We limit the # of errors printed to avoid spam.
@@ -171,7 +172,8 @@ static void
_EmitAnyExtraLogInfo(char const *fname)
{
// This function can't cause any heap allocation, be careful.
- if (FILE* outFile = fopen(fname, "a")) {
+ FILE* outFile = NULL;
+ if (outFile = ArchOpenFile(fname, "a")) {
_EmitAnyExtraLogInfo(outFile);
fclose(outFile);
}
@@ -195,11 +197,17 @@ static const char* const stackTracePrefix = "st";
static const char* stackTraceCmd = nullptr;
static const char* const* stackTraceArgv = nullptr;
+#if defined(ARCH_OS_WINDOWS)
+static long _GetAppElapsedTime();
+#else
static time_t _GetAppElapsedTime();
+#endif
+#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
// asgetenv() want's this but we can't declare it inside the namespace.
extern char **environ;
+#endif
namespace {
@@ -325,6 +333,12 @@ char* asitoa(char* s, long x)
int _GetStackTraceName(char* buf, size_t len)
{
+#if defined(ARCH_OS_WINDOWS)
+ int pid = _getpid();
+#else
+ int pid = getpid();
+#endif
+
// Take care to avoid non-async-safe functions.
// NOTE: This doesn't protect against other threads changing the
// temporary directory or program name for errors.
@@ -337,7 +351,7 @@ int _GetStackTraceName(char* buf, size_t len)
1 + // "_"
asstrlen(ArchGetProgramNameForErrors()) +
1 + // "."
- asNumDigits(getpid()) +
+ asNumDigits(pid) +
1; // "\0"
// Fill in buf with the default name.
@@ -354,13 +368,20 @@ int _GetStackTraceName(char* buf, size_t len)
end = asstrcpy(end, "_");
end = asstrcpy(end, ArchGetProgramNameForErrors());
end = asstrcpy(end, ".");
- end = asitoa(end, getpid());
+ end = asitoa(end, pid);
}
// Return a name that isn't currently in use. Simultaneously create
// the empty file.
int suffix = 0;
- int fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640);
+#if defined(ARCH_OS_WINDOWS)
+ int fd;
+ _sopen_s(&fd, buf, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL,
+ _SH_DENYNO, _S_IREAD | _S_IWRITE);
+#else
+ int fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640);
+#endif
+
while (fd == -1 and errno == EEXIST) {
// File exists. Try a new suffix if there's space.
++suffix;
@@ -371,10 +392,15 @@ int _GetStackTraceName(char* buf, size_t len)
}
asstrcpy(end, ".");
asitoa(end + 1, suffix);
- fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640);
+#if defined(ARCH_OS_WINDOWS)
+ _sopen_s(&fd, buf, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL,
+ _SH_DENYNO, _S_IREAD | _S_IWRITE);
+#else
+ fd = open(buf, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0640);
+#endif
}
if (fd != -1) {
- close(fd);
+ ArchCloseFile(fd);
fd = 0;
}
return fd;
@@ -435,11 +461,16 @@ _MakeArgv(
static int
nonLockingFork()
{
+#if defined(ARCH_OS_WINDOWS)
+ printf("nonLockingFork() not yet implemented on Windows\n");
+ return 0;
+#else
if (Arch_nonLockingFork != NULL) {
return (Arch_nonLockingFork)();
} else {
return fork();
}
+#endif
}
#if defined(ARCH_OS_LINUX)
@@ -502,6 +533,8 @@ nonLockingExecv( const char *path, char *const argv[])
{
#if defined(ARCH_OS_LINUX)
return nonLockingLinux__execve (path, argv, __environ);
+#elif defined(ARCH_OS_WINDOWS)
+ return static_cast(_execv(path, argv));
#else
return execv(path, argv);
#endif
@@ -535,6 +568,12 @@ getBase(const char* path)
static
int _LogStackTraceForPid(const char *logfile)
{
+#if defined(ARCH_OS_WINDOWS)
+ int pid = _getpid();
+#else
+ int pid = getpid();
+#endif
+
// Get the command to run.
const char* cmd = asgetenv("ARCH_POSTMORTEM");
if (not cmd) {
@@ -547,7 +586,7 @@ int _LogStackTraceForPid(const char *logfile)
// Construct the substitutions.
char pidBuffer[numericBufferSize], timeBuffer[numericBufferSize];
- asitoa(pidBuffer, getpid());
+ asitoa(pidBuffer, pid);
asitoa(timeBuffer, _GetAppElapsedTime());
const char* const substitutions[3][2] = {
"$pid", pidBuffer, "$log", logfile, "$time", timeBuffer
@@ -558,7 +597,11 @@ int _LogStackTraceForPid(const char *logfile)
const char* argv[maxArgs];
if (not _MakeArgv(argv, maxArgs, cmd, stackTraceArgv, substitutions, 2)) {
static const char msg[] = "Too many arguments to postmortem command\n";
+#if defined(ARCH_OS_WINDOWS)
+ _write(2, msg, sizeof(msg) - 1);
+#else
write(2, msg, sizeof(msg) - 1);
+#endif
return 0;
}
@@ -632,7 +675,7 @@ void
ArchSetProgramInfoForErrors(const std::string& key,
const std::string& value)
{
- Locker lock(_progInfoForErrorsMutex);
+ std::lock_guard lock(_progInfoForErrorsMutex);
if (value.empty()) {
_progInfoMap.erase(key);
@@ -652,13 +695,17 @@ ArchSetProgramInfoForErrors(const std::string& key,
if (_progInfoForErrors)
free(_progInfoForErrors);
- _progInfoForErrors = strdup(ss.str().c_str());
+#if defined(ARCH_OS_WINDOWS)
+ _progInfoForErrors = _strdup(ss.str().c_str());
+#else
+ _progInfoForErrors = strdup(ss.str().c_str());
+#endif
}
std::string
ArchGetProgramInfoForErrors(const std::string& key) {
- Locker lock(_progInfoForErrorsMutex);
+ std::lock_guard lock(_progInfoForErrorsMutex);
Arch_ProgInfoMap::iterator iter = _progInfoMap.find(key);
std::string result;
@@ -671,7 +718,7 @@ ArchGetProgramInfoForErrors(const std::string& key) {
void
ArchSetExtraLogInfoForErrors(const std::string &key, char const *text)
{
- Locker lock(_logInfoForErrorsMutex);
+ std::lock_guard lock(_logInfoForErrorsMutex);
if (not text or not strlen(text)) {
_logInfoForErrors.erase(key);
} else {
@@ -692,7 +739,11 @@ ArchSetProgramNameForErrors( const char *progName )
free(_progNameForErrors);
if (progName)
- _progNameForErrors = strdup(getBase(progName));
+#if defined(ARCH_OS_WINDOWS)
+ _progNameForErrors = _strdup(getBase(progName));
+#else
+ _progNameForErrors = strdup(getBase(progName));
+#endif
else
_progNameForErrors = NULL;
}
@@ -713,6 +764,26 @@ ArchGetProgramNameForErrors()
return "libArch";
}
+#if defined(ARCH_OS_WINDOWS)
+static long
+_GetAppElapsedTime()
+{
+ FILETIME starttime;
+ FILETIME exittime;
+ FILETIME kerneltime;
+ FILETIME usertime;
+ ULARGE_INTEGER li;
+
+ if (::GetProcessTimes(GetCurrentProcess(),
+ &starttime, &exittime, &kerneltime, &usertime) == 0)
+ {
+ printf("_GetAppElapsedTime failed\n");
+ return time_t(0);
+ }
+ memcpy(&li, &usertime, sizeof(FILETIME));
+ return static_cast(time_t(li.QuadPart / 10000000ULL - 11644473600ULL));
+}
+#else
static time_t
_GetAppElapsedTime()
{
@@ -733,10 +804,17 @@ _GetAppElapsedTime()
//
return time(0) - _appLaunchTime;
}
+#endif
static void
_InvokeSessionLogger(const char* progname, const char *stackTrace)
{
+#if defined(ARCH_OS_WINDOWS)
+ int pid = _getpid();
+#else
+ int pid = getpid();
+#endif
+
// Get the command to run.
const char* cmd = asgetenv("ARCH_LOGSESSION");
const char* const* srcArgv =
@@ -751,7 +829,7 @@ _InvokeSessionLogger(const char* progname, const char *stackTrace)
// Construct the substitutions.
char pidBuffer[numericBufferSize], timeBuffer[numericBufferSize];
- asitoa(pidBuffer, getpid());
+ asitoa(pidBuffer, pid);
asitoa(timeBuffer, _GetAppElapsedTime());
const char* const substitutions[4][2] = {
"$pid", pidBuffer, "$time", timeBuffer,
@@ -763,7 +841,11 @@ _InvokeSessionLogger(const char* progname, const char *stackTrace)
const char* argv[maxArgs];
if (not _MakeArgv(argv, maxArgs, cmd, srcArgv, substitutions, 4)) {
static const char msg[] = "Too many arguments to log session command\n";
+#if defined(ARCH_OS_WINDOWS)
+ _write(2, msg, sizeof(msg) - 1);
+#else
write(2, msg, sizeof(msg) - 1);
+#endif
return;
}
@@ -783,18 +865,20 @@ _FinishLoggingFatalStackTrace(const char *progname, const char *stackTrace,
{
if (!crashingHard && sessionLog) {
// If we were given a session log, cat it to the end of the stack.
- if (FILE* stackFd = fopen(stackTrace, "a")) {
- if (FILE* sessionLogFd = fopen(sessionLog, "r")) {
- fprintf(stackFd,"\n\n********** Session Log **********\n\n");
- // Cat the sesion log
- char line[4096];
- while (fgets(line, 4096, sessionLogFd)) {
- fputs(line, stackFd);
+ FILE* stackFd;
+ if (stackFd = ArchOpenFile(stackTrace, "a")) {
+ FILE* sessionLogFd;
+ if (sessionLogFd = ArchOpenFile(sessionLog, "r")) {
+ fprintf(stackFd,"\n\n********** Session Log **********\n\n");
+ // Cat the sesion log
+ char line[4096];
+ while (fgets(line, 4096, sessionLogFd)) {
+ fputs(line, stackFd);
+ }
+ fclose(sessionLogFd);
+ }
+ fclose(stackFd);
}
- fclose(sessionLogFd);
- }
- fclose(stackFd);
- }
}
// Add trace to database if _shouldLogStackToDb is true
@@ -851,13 +935,18 @@ ArchLogPostMortem(const char* reason, const char* message /* = nullptr */)
if (_GetStackTraceName(logfile, sizeof(logfile)) == -1) {
// Cannot create the logfile.
static const char msg[] = "Cannot create a log file\n";
+#if defined(ARCH_OS_WINDOWS)
+ _write(2, msg, sizeof(msg) - 1);
+#else
write(2, msg, sizeof(msg) - 1);
+#endif
busy.clear(std::memory_order_release);
return;
}
// Write reason for stack trace to logfile.
- if (FILE* stackFd = fopen(logfile, "a")) {
+ FILE* stackFd;
+ if (stackFd = ArchOpenFile(logfile, "a")) {
if (reason) {
fprintf(stackFd, "This stack trace was requested because: %s\n",
reason);
@@ -882,7 +971,7 @@ ArchLogPostMortem(const char* reason, const char* message /* = nullptr */)
// print out any registered program info
{
- Locker lock(_progInfoForErrorsMutex);
+ std::lock_guard lock(_progInfoForErrorsMutex);
if (_progInfoForErrors) {
fprintf(stderr, "%s", _progInfoForErrors);
}
@@ -951,14 +1040,18 @@ ArchLogStackTrace(const std::string& progname, const std::string& reason,
// print out any registered program info
{
- Locker lock(_progInfoForErrorsMutex);
+ std::lock_guard lock(_progInfoForErrorsMutex);
if (_progInfoForErrors) {
fprintf(stderr, "%s", _progInfoForErrors);
}
}
if (fd != -1) {
- FILE* fout = fdopen(fd, "w");
+#if defined(ARCH_OS_WINDOWS)
+ FILE* fout = _fdopen(fd, "w");
+#else
+ FILE* fout = fdopen(fd, "w");
+#endif
fprintf(stderr, "The stack can be found in %s:%s\n"
"--------------------------------------------------------------"
"\n", hostname, tmpFile.c_str());
@@ -1014,7 +1107,7 @@ _LogStackTraceToOutputIterator(OutputIterator oi, size_t maxDepth, bool addEndl)
}
inFile.close();
- unlink(logfile);
+ ArchUnlinkFile(logfile);
}
#endif
@@ -1288,6 +1381,10 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[],
int timeout, ArchCrashHandlerSystemCB callback,
void* userData)
{
+#if defined(ARCH_OS_WINDOWS)
+ printf("ArchCrashHandlerSystemv unimplemented for Windows\n");
+ return -1;
+#else
struct sigaction act, oldact;
int retval = 0;
int savedErrno;
@@ -1307,7 +1404,7 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[],
nonLockingExecv(pathname, argv); /* use non-locking execv */
/* exec() failed */
fprintf(stderr, "FAIL: Unable to exec() crash handler %s: %s\n",
- pathname, strerror(errno));
+ pathname, ArchStrerror(errno).c_str());
_exit(127);
}
else {
@@ -1394,17 +1491,20 @@ ArchCrashHandlerSystemv(const char* pathname, char *const argv[],
errno = savedErrno;
return retval;
+#endif
}
/* test thread for crashing (loops forever.) */
static void *
arch_athread(void *)
{
+#if !defined(ARCH_OS_WINDOWS)
while (1) {} /* loop forever */
pthread_exit((void *) 0);
#if defined(ARCH_OS_DARWIN)
return (void*)0;
#endif
+#endif
}
/*
@@ -1417,6 +1517,7 @@ arch_athread(void *)
void
ArchTestCrash(bool spawnthread)
{
+#if !defined(ARCH_OS_WINDOWS)
pthread_t tid;
char *overwrite, *another;
@@ -1466,4 +1567,5 @@ ArchTestCrash(bool spawnthread)
fprintf(stderr,"FAILED to crash! Aborting.\n");
abort();
+#endif
}
diff --git a/pxr/base/lib/arch/stackTrace.h b/pxr/base/lib/arch/stackTrace.h
index 103c8011c5..0485ae3aa4 100644
--- a/pxr/base/lib/arch/stackTrace.h
+++ b/pxr/base/lib/arch/stackTrace.h
@@ -24,7 +24,13 @@
#ifndef ARCH_STACKTRACE_H
#define ARCH_STACKTRACE_H
+/// \file arch/stackTrace.h
+/// \ingroup group_arch_Diagnostics
+/// Architecture-specific call-stack tracing routines.
+
#include "pxr/base/arch/defines.h"
+#include "pxr/base/arch/api.h"
+
#include
#include
#include
@@ -32,354 +38,280 @@
#include
#include
-/*!
- * \file stackTrace.h
- * \brief Architecture-specific call-stack tracing routines.
- * \ingroup group_arch_Diagnostics
- */
-
-/*!
- * \brief Dumps call-stack info to a file, and prints an informative
- * message.
- * \ingroup group_arch_Diagnostics
- *
- * The reason for the trace should be supplied in \p reason. This routine
- * can be slow and is intended to be called for a fatal error, such as a
- * caught coredump signal, but may be called at any time. An additional
- * message may be provided in \p message. If \p reason is \c NULL then
- * this function only writes \p message to the banner (if any).
- *
- * This function is implemented by calling an external program. This
- * is suitable for times where the current process may be corrupted. In
- * other cases, using \c ArchPrintStackTrace() or other related functions
- * would be much faster.
- *
- * Note the use of \c char* as opposed to \c string: this is intentional,
- * because we are trying to use only async-safe function from here on and
- * malloc() is not async-safe.
- */
+/// \addtogroup group_arch_Diagnostics
+///@{
+
+/// Dumps call-stack info to a file, and prints an informative message.
+///
+/// The reason for the trace should be supplied in \p reason. This routine
+/// can be slow and is intended to be called for a fatal error, such as a
+/// caught coredump signal, but may be called at any time. An additional
+/// message may be provided in \p message. If \p reason is \c NULL then this
+/// function only writes \p message to the banner (if any).
+///
+/// This function is implemented by calling an external program. This is
+/// suitable for times where the current process may be corrupted. In other
+/// cases, using \c ArchPrintStackTrace() or other related functions would be
+/// much faster.
+///
+/// Note the use of \c char* as opposed to \c string: this is intentional,
+/// because we are trying to use only async-safe function from here on and
+/// malloc() is not async-safe.
+ARCH_API
void ArchLogPostMortem(const char* reason, const char* message = nullptr);
-/*!
- * \brief Sets the command line that gathers call-stack info.
- * \ingroup group_arch_Diagnostics
- *
- * This function sets the command line to execute to gather and log call-stack
- * info. \p argv must be NULL terminated. \p command and/or \p argv may be
- * NULL to suppress execution. Otherwise argv[0] must be the full path to the
- * program to execute, typically \p command or "$cmd" as described below.
- *
- * \p command and \p argv are not copied and must remain valid until the next
- * call to \c ArchSetPostMortem.
- *
- * Simple substitution is supported on argv elements:
- * \li $cmd: Substitutes the command pathname, or $ARCH_POSTMORTEM if set
- * \li $pid: Substitutes the process id
- * \li $log: Substitutes the log pathname
- * \li $time: Substitutes the user time (if available, else wall time)
- *
- * \sa ArchLogPostMortem
- */
+/// Sets the command line that gathers call-stack info.
+///
+/// This function sets the command line to execute to gather and log
+/// call-stack info. \p argv must be NULL terminated. \p command and/or \p
+/// argv may be NULL to suppress execution. Otherwise argv[0] must be the
+/// full path to the program to execute, typically \p command or "$cmd" as
+/// described below.
+///
+/// \p command and \p argv are not copied and must remain valid until the next
+/// call to \c ArchSetPostMortem.
+///
+/// Simple substitution is supported on argv elements:
+/// \li $cmd: Substitutes the command pathname, or $ARCH_POSTMORTEM if set
+/// \li $pid: Substitutes the process id
+/// \li $log: Substitutes the log pathname
+/// \li $time: Substitutes the user time (if available, else wall time)
+///
+/// \sa ArchLogPostMortem
+ARCH_API
void ArchSetPostMortem(const char* command, const char *const argv[]);
-/*!
- * \brief Log session info.
- * \ingroup group_arch_Diagnostics
- *
- * Optionally indicate that this is due to a crash by providing
- * the path to a file containing a stack trace in \p crashStackTrace.
- *
- */
+/// Log session info.
+///
+/// Optionally indicate that this is due to a crash by providing
+/// the path to a file containing a stack trace in \p crashStackTrace.
+///
+ARCH_API
void ArchLogSessionInfo(const char *crashStackTrace=NULL);
-/*!
- * \brief Sets the command line to log sessions.
- * \ingroup group_arch_Diagnostics
- *
- * This function sets the command line to execute to log session info.
- * \p argv is used if no crash stack trace is provided, otherwise
- * \p crashArgv is used. Both must be NULL terminated. If \p command
- * or \p argv is NULL then non-crashes are not logged; if \p command
- * or \p crashArgv is NULL then crashes are not logged. If not NULL then
- * argv[0] and crashArgv[0] must be full path to the program to execute,
- * typically \p command or "$cmd" as described below.
- *
- * \p command, \p argv, and \p crashArgv are not copied and must remain
- * valid until the next call to \c ArchSetLogSession.
- *
- * Simple substitution is supported on argv elements:
- * \li $cmd: Substitutes the command pathname, or $ARCH_LOGSESSION if set
- * \li $prog Substitutes the program name
- * \li $pid: Substitutes the process id
- * \li $time: Substitutes the user time (if available, else wall time)
- * \li $stack: Substitutes the crash stack string (only in crashArgv)
- *
- * \sa ArchLogSessionInfo
- */
+/// Sets the command line to log sessions.
+///
+/// This function sets the command line to execute to log session info. \p
+/// argv is used if no crash stack trace is provided, otherwise \p crashArgv
+/// is used. Both must be NULL terminated. If \p command or \p argv is NULL
+/// then non-crashes are not logged; if \p command or \p crashArgv is NULL
+/// then crashes are not logged. If not NULL then argv[0] and crashArgv[0]
+/// must be full path to the program to execute, typically \p command or
+/// "$cmd" as described below.
+///
+/// \p command, \p argv, and \p crashArgv are not copied and must remain valid
+/// until the next call to \c ArchSetLogSession.
+///
+/// Simple substitution is supported on argv elements:
+/// \li $cmd: Substitutes the command pathname, or $ARCH_LOGSESSION if set
+/// \li $prog Substitutes the program name
+/// \li $pid: Substitutes the process id
+/// \li $time: Substitutes the user time (if available, else wall time)
+/// \li $stack: Substitutes the crash stack string (only in crashArgv)
+///
+/// \sa ArchLogSessionInfo
+ARCH_API
void ArchSetLogSession(const char* command,
const char* const argv[],
const char* const crashArgv[]);
-/*!
- * \brief Register the callback to invoke logging at
- * end of a successful session.
- * \ingroup group_arch_Diagnostics
- *
- * This function registers ArchLogSessionInfo()
- * and records the current timestamp, to send up-time
- * to the DB upon exiting.
- */
+/// Register the callback to invoke logging at end of a successful session.
+///
+/// This function registers ArchLogSessionInfo() and records the current
+/// timestamp, to send up-time to the DB upon exiting.
+ARCH_API
void ArchEnableSessionLogging();
-// Again, 2 versions, one for 2x and one for 3x.
-/*!
- * \brief Print a stack trace to the given FILE *.
- * \ingroup group_arch_Diagnostics
- *
- * Prints out a stack trace to the given FILE *. Will call
- * Prints out a stack trace to the given stream (\c man \c stdio). Will call
- * ArchLoadSymbols() if symbols have not yet been loaded.
- */
-void ArchPrintStackTrace(FILE *fout, const std::string& programName,
- const std::string& reason);
-
-/*!
- * \brief Print a stack trace to the given FILE *.
- * \ingroup group_arch_Diagnostics
- *
- * Prints out a stack trace to the given FILE *. Will call
- * Prints out a stack trace to the given stream (\c man \c stdio). Will call
- * ArchLoadSymbols() if symbols have not yet been loaded.
- */
+/// Print a stack trace to the given FILE pointer.
+ARCH_API
+void ArchPrintStackTrace(FILE *fout,
+ const std::string& programName,
+ const std::string& reason);
+
+/// Print a stack trace to the given FILE pointer.
+/// This function uses ArchGetProgramInfoForErrors as the \c programName.
+/// \overload
+ARCH_API
void ArchPrintStackTrace(FILE *fout, const std::string& reason);
+/// Print a stack trace to the given ostream.
+/// \overload
+void ArchPrintStackTrace(std::ostream& out,
+ const std::string& programName,
+ const std::string& reason);
-/*!
- * \brief Print a stack trace to the given iostream.
- * \ingroup group_arch_Diagnostics
- *
- * see above
- */
-void ArchPrintStackTrace(std::ostream& out,
- const std::string& programName,
- const std::string& reason);
-
-/*!
- * \brief Print a stack trace to the given iostream.
- * \ingroup group_arch_Diagnostics
- *
- * see above
- */
+/// Print a stack trace to the given iostream.
+/// This function uses ArchGetProgramInfoForErrors as the \c programName.
+/// \overload
+ARCH_API
void ArchPrintStackTrace(std::ostream& out, const std::string& reason);
-/*!
- * \brief A callback to get a symbolic representation of an address.
- * \ingroup group_arch_Diagnostics
- */
+/// A callback to get a symbolic representation of an address.
typedef std::function ArchStackTraceCallback;
-/*!
- * \brief Sets a callback to get a symbolic representation of an address.
- * \ingroup group_arch_Diagnostics
- *
- * The callback returns a string for an address in a stack trace,
- * typically including the name of the function containing the address.
- * \p cb may be \c NULL to use a default implementation.
- */
+/// Sets a callback to get a symbolic representation of an address.
+///
+/// The callback returns a string for an address in a stack trace, typically
+/// including the name of the function containing the address. \p cb may be \c
+/// NULL to use a default implementation.
+ARCH_API
void ArchSetStackTraceCallback(const ArchStackTraceCallback& cb);
-/*!
- * \brief Returns the callback to get a symbolic representation of an address.
- * \ingroup group_arch_Diagnostics
- *
- * \sa ArchSetStackTraceCallback
- */
+/// Returns the callback to get a symbolic representation of an address.
+/// \sa ArchSetStackTraceCallback
+ARCH_API
void ArchGetStackTraceCallback(ArchStackTraceCallback* cb);
-/*!
- * \brief Returns the set value for the application's launch time.
- * \ingroup group_arch_Diagnostics
- *
- * The timestamp for this value is set when the Arch library is initialized.
- */
+/// Returns the set value for the application's launch time.
+/// The timestamp for this value is set when the arch library is initialized.
+ARCH_API
time_t ArchGetAppLaunchTime();
-/*!
- * \brief Enables or disables the automatic logging of crash information.
- * \ingroup group_arch_Diagnostics
- *
- * This function controls whether the stack trace and build information is
- * automatically caught and stored to an internal database when a fatal
- * crash occurs.
- */
-void ArchSetFatalStackLogging( bool flag );
-
-/*!
- * \brief Returns whether automatic logging of fatal crashes is enabled
- * \ingroup group_arch_Diagnostics
- *
- * This is set to false by default.
- */
+/// Enables or disables the automatic logging of crash information.
+///
+/// This function controls whether the stack trace and build information is
+/// automatically caught and stored to an internal database when a fatal crash
+/// occurs.
+ARCH_API
+void ArchSetFatalStackLogging(bool flag);
+
+/// Returns whether automatic logging of fatal crashes is enabled
+/// This is set to false by default.
+/// \see ArchSetFatalStackLogging
+ARCH_API
bool ArchGetFatalStackLogging();
-/*!
- * \brief Sets the program name to be used in diagnostic output
- * \ingroup group_arch_Diagnostics
- *
- * The default value is initialized to ArchGetExecutablePath().
- */
-void ArchSetProgramNameForErrors( const char * progName );
-
-/*!
- * \brief Returns the currently set program name for reporting errors.
- * \ingroup group_arch_Diagnostics
- *
- * Defaults to ArchGetExecutablePath().
- */
+/// Sets the program name to be used in diagnostic output
+///
+/// The default value is initialized to ArchGetExecutablePath().
+ARCH_API
+void ArchSetProgramNameForErrors(const char * progName);
+
+/// Returns the currently set program name for reporting errors.
+/// Defaults to ArchGetExecutablePath().
+ARCH_API
const char * ArchGetProgramNameForErrors();
-/*!
- * \brief Sets additional program info to be reported to the terminal in case of
- * a fatal error.
- * \ingroup group_arch_Diagnostics
- *
- */
+/// Sets additional program info to be reported to the terminal in case of a
+/// fatal error.
+ARCH_API
void ArchSetProgramInfoForErrors( const std::string& key, const std::string& value );
-/*!
- * \brief Returns currently set program info.
- * \ingroup group_arch_Diagnostics
- *
- */
+/// Returns currently set program info.
+/// \see ArchSetExtraLogInfoForErrors
+ARCH_API
std::string ArchGetProgramInfoForErrors(const std::string& key);
-
-/*!
- * \brief Stores (or removes if \p text is NULL) a pointer to additional log
- * data that will be output in the stack trace log in case of a fatal error.
- * Note that the pointer \p text is copied, not the pointed-to text. Thus it is
- * the caller's responsibility to ensure that \p text is valid until the caller
- * removes it by invoking this function again with text==NULL.
- * \ingroup group_arch_Diagnostics
- */
+/// Stores (or removes if \p text is NULL) a pointer to additional log data
+/// that will be output in the stack trace log in case of a fatal error. Note
+/// that the pointer \p text is copied, not the pointed-to text. Thus it is
+/// the caller's responsibility to ensure that \p text is valid until the
+/// caller removes it by invoking this function again with text==NULL.
+ARCH_API
void ArchSetExtraLogInfoForErrors(const std::string &key, char const *text);
-/*!
- * \brief Logs a stack trace to a file in /var/tmp.
- * \ingroup group_arch_Diagnostics
- *
- * This function is similar to \c ArchLogPostMortem(), but will not fork an
- * external process and only reports a stack trace. A file in /var/tmp is
- * created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
- * make a unique extension for the file. If \c sessionLog is specified,
- * then it will be appended to this file. A message is printed to \c stderr
- * reporting that a stack trace has been taken and what file it has been
- * written to. And if \c fatal is true, then the stack trace will be added
- * to the stack_trace database table.
- */
-void ArchLogStackTrace(const std::string& progName, const std::string& reason,
- bool fatal = false,
- const std::string& sessionLog = "");
-
-/*!
- * \brief Logs a stack trace to a file in /var/tmp.
- * \ingroup group_arch_Diagnostics
- *
- * This function is similar to \c ArchLogPostMortem(), but will not fork an
- * external process and only reports a stack trace. A file in /var/tmp is
- * created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
- * make a unique extension for the file. If \c sessionLog is specified,
- * then it will be appended to this file. A message is printed to \c stderr
- * reporting that a stack trace has been taken and what file it has been
- * written to. And if \c fatal is true, then the stack trace will be added
- * to the stack_trace database table.
- */
+/// Logs a stack trace to a file in /var/tmp.
+///
+/// This function is similar to \c ArchLogPostMortem(), but will not fork an
+/// external process and only reports a stack trace. A file in /var/tmp is
+/// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
+/// make a unique extension for the file. If \c sessionLog is specified, then
+/// it will be appended to this file. A message is printed to \c stderr
+/// reporting that a stack trace has been taken and what file it has been
+/// written to. And if \c fatal is true, then the stack trace will be added
+/// to the stack_trace database table.
+ARCH_API
+void ArchLogStackTrace(const std::string& progName,
+ const std::string& reason,
+ bool fatal = false,
+ const std::string& sessionLog = "");
+
+/// Logs a stack trace to a file in /var/tmp.
+///
+/// This function is similar to \c ArchLogPostMortem(), but will not fork an
+/// external process and only reports a stack trace. A file in /var/tmp is
+/// created with the name \c st_APPNAME.XXXXXX, where \c mktemp is used to
+/// make a unique extension for the file. If \c sessionLog is specified,
+/// then it will be appended to this file. A message is printed to \c stderr
+/// reporting that a stack trace has been taken and what file it has been
+/// written to. And if \c fatal is true, then the stack trace will be added
+/// to the stack_trace database table.
+ARCH_API
void ArchLogStackTrace(const std::string& reason,
bool fatal = false,
const std::string& sessionLog = "");
-/*!
- * \brief Return stack trace.
- * \ingroup group_arch_Diagnostics
- *
- * This function will return a vector of strings containing the
- * current stack. The vector will be of maximum size \p maxDepth.
- */
+/// Return stack trace.
+///
+/// This function will return a vector of strings containing the current
+/// stack. The vector will be of maximum size \p maxDepth.
+ARCH_API
std::vector ArchGetStackTrace(size_t maxDepth);
-/*!
- * \brief Save frames of current stack
- * \ingroup group_arch_Diagnostics
- *
- * This function saves at maximum \c maxDepth frames of the current
- * stack into the vector \c frames.
- *
- */
+/// Save frames of current stack
+///
+/// This function saves at maximum \c maxDepth frames of the current stack
+/// into the vector \c frames.
+ARCH_API
void ArchGetStackFrames(size_t maxDepth, std::vector *frames);
-/*!
- * \brief Save frames of current stack.
- * \ingroup group_arch_Diagnostics
- *
- * This function saves at maximum \p maxDepth frames of the current
- * stack into the vector \p frames, skipping the first \p numFramesToSkipAtTop
- * frames. The first frame will be at depth \p numFramesToSkipAtTop and the
- * last at depth \p numFramesToSkipAtTop + \p maxDepth - 1.
- *
- */
+/// Save frames of current stack.
+///
+/// This function saves at maximum \p maxDepth frames of the current stack
+/// into the vector \p frames, skipping the first \p numFramesToSkipAtTop
+/// frames. The first frame will be at depth \p numFramesToSkipAtTop and the
+/// last at depth \p numFramesToSkipAtTop + \p maxDepth - 1.
+ARCH_API
void ArchGetStackFrames(size_t maxDepth, size_t numFramesToSkipAtTop,
std::vector *frames);
-/*!
- * \brief Print stack frames to the given iostream.
- * \ingroup group_arch_Diagnostics
- *
- */
+/// Print stack frames to the given iostream.
+ARCH_API
void ArchPrintStackFrames(std::ostream& out,
const std::vector &frames);
+/// Callback for handling crashes.
+/// \see ArchCrashHandlerSystemv
typedef void (*ArchCrashHandlerSystemCB)(void* userData);
-/*!
- * \brief Replacement for 'system' safe for a crash handler
- * \ingroup group_arch_Diagnostics
- *
- * This function is a substitute for system() which does not allocate
- * or free any data, and times out after \c timeout seconds if the
- * operation in \c argv is not complete. Unlike system, it takes the
- * full \c pathname of the program to run, and won't search the path.
- * Also unlike system, \c argv[] are the separated arguments, starting
- * with the program's name, as for execv. \c callback is called every
- * second. \c userData is passed to \c callback. \c callback can be used,
- * for example, to print a '.' repeatedly to show progress. The alarm
- * used in this function could interfere with setitimer or other calls
- * to alarm, and this function uses non-locking fork and exec if available
- * so should not generally be used except following a catastrophe.
- */
+
+/// Replacement for 'system' safe for a crash handler
+///
+/// This function is a substitute for system() which does not allocate or free
+/// any data, and times out after \c timeout seconds if the operation in \c
+/// argv is not complete. Unlike system, it takes the full \c pathname of the
+/// program to run, and won't search the path. Also unlike system, \c argv[]
+/// are the separated arguments, starting with the program's name, as for
+/// execv. \c callback is called every second. \c userData is passed to \c
+/// callback. \c callback can be used, for example, to print a '.' repeatedly
+/// to show progress. The alarm used in this function could interfere with
+/// setitimer or other calls to alarm, and this function uses non-locking fork
+/// and exec if available so should not generally be used except following a
+/// catastrophe.
+ARCH_API
int ArchCrashHandlerSystemv(const char* pathname, char *const argv[],
int timeout, ArchCrashHandlerSystemCB callback,
void* userData);
-/*!
- * \brief Crash, to test crash behavior.
- * \ingroup group_arch_Diagnostics
- *
- * This function causes the calling program to crash by doing bad malloc
- * and free things. If \c spawnthread is true, it spawns a thread which
- * remains alive during the crash. It aborts if it fails to crash.
- *
- */
+/// Crash, to test crash behavior.
+///
+/// This function causes the calling program to crash by doing bad malloc
+/// and free things. If \c spawnthread is true, it spawns a thread which
+/// remains alive during the crash. It aborts if it fails to crash.
+///
+/// \private
+ARCH_API
void ArchTestCrash(bool spawnthread);
#if defined(ARCH_OS_DARWIN)
- /* XXX:---:20030825 Mac OS X has no ETIME. ECANCELED seems
- * to have about the closest meaning to the actual error here.
- * The operation is timing out, not being explicitly canceled,
- * but it is canceled.
- */
+// Mac OS X has no ETIME. ECANCELED seems to have about the closest meaning to
+// the actual error here. The operation is timing out, not being explicitly
+// canceled, but it is canceled.
#ifndef ETIME
#define ETIME ECANCELED
#endif // end ETIME
#endif // end ARCH_OS_DARWIN
+///@}
+
#endif // ARCH_STACKTRACE_H
diff --git a/pxr/base/lib/arch/symbols.cpp b/pxr/base/lib/arch/symbols.cpp
index 2064d0001a..4d2bd1983f 100644
--- a/pxr/base/lib/arch/symbols.cpp
+++ b/pxr/base/lib/arch/symbols.cpp
@@ -23,8 +23,13 @@
//
#include "pxr/base/arch/symbols.h"
#include "pxr/base/arch/defines.h"
+#include "pxr/base/arch/fileSystem.h"
+#include "pxr/base/arch/errno.h"
#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
#include
+#elif defined(ARCH_OS_WINDOWS)
+#include
+#include
#endif
bool
@@ -50,6 +55,26 @@ ArchGetAddressInfo(
}
return true;
}
+#elif defined(ARCH_OS_WINDOWS)
+ HMODULE module = nullptr;
+
+ if (objectPath)
+ {
+ if (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ reinterpret_cast(address),
+ &module))
+ {
+ char modName[ARCH_PATH_MAX + 1] = {0};
+ if(GetModuleFileName(module, modName, ARCH_PATH_MAX))
+ {
+ objectPath->assign(modName);
+ return true;
+ }
+ }
+ else
+ ArchStrSysError(::GetLastError());
+ }
#endif
return false;
}
diff --git a/pxr/base/lib/arch/symbols.h b/pxr/base/lib/arch/symbols.h
index 0ed273fd5f..0f4df1ea0e 100644
--- a/pxr/base/lib/arch/symbols.h
+++ b/pxr/base/lib/arch/symbols.h
@@ -24,26 +24,27 @@
#ifndef ARCH_SYMBOLS_H
#define ARCH_SYMBOLS_H
-#include
+/// \file arch/symbols.h
+/// \ingroup group_arch_Diagnostics
+/// Architecture-specific symbol lookup routines.
-/*!
- * \file symbols.h
- * \brief Architecture-specific symbol lookup routines.
- * \ingroup group_arch_Diagnostics
- */
+#include "pxr/base/arch/api.h"
+#include
-/*!
- * Returns information about the address \p address in the running program.
- * Returns \c false if no information can be found, otherwise returns \c true
- * and modifies the other arguments: \p objectPath is set to the path to
- * the executable or library the address is found in, \p baseAddress is the
- * address where that object is loaded, \p symbolName is the symbolic name
- * of the thing containing the address, and \p symbolAddress is the starting
- * address of that thing. If no thing is found to contain the address then
- * \p symbolName is cleared and \p symbolAddress is set to \c NULL.
- * Any of the arguments except \p address can be \c NULL if the result isn't
- * needed. This will return \c false if \c NULL is passed to \p address.
- */
+/// Returns information about the address \p address in the running program.
+///
+/// Returns \c false if no information can be found, otherwise returns \c true
+/// and modifies the other arguments: \p objectPath is set to the path to the
+/// executable or library the address is found in, \p baseAddress is the
+/// address where that object is loaded, \p symbolName is the symbolic name of
+/// the thing containing the address, and \p symbolAddress is the starting
+/// address of that thing. If no thing is found to contain the address then
+/// \p symbolName is cleared and \p symbolAddress is set to \c NULL. Any of
+/// the arguments except \p address can be \c NULL if the result isn't needed.
+/// This will return \c false if \c NULL is passed to \p address.
+///
+/// \ingroup group_arch_Diagnostics
+ARCH_API
bool ArchGetAddressInfo(void* address,
std::string* objectPath, void** baseAddress,
std::string* symbolName, void** symbolAddress);
diff --git a/pxr/base/lib/arch/systemInfo.cpp b/pxr/base/lib/arch/systemInfo.cpp
index d68388e61d..859da55d1c 100644
--- a/pxr/base/lib/arch/systemInfo.cpp
+++ b/pxr/base/lib/arch/systemInfo.cpp
@@ -21,13 +21,26 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/pragmas.h"
+#include "pxr/base/arch/api.h"
#include "pxr/base/arch/error.h"
-#include "pxr/base/arch/defines.h"
#include "pxr/base/arch/stackTrace.h"
+#include "pxr/base/arch/env.h"
#include
#include
+#if defined(ARCH_OS_WINDOWS)
+#include // for timeval
+#include
+#include
+ARCH_PRAGMA_MACRO_REDEFINITION
+#include
+ARCH_PRAGMA_RESTORE
+#include
+#else
#include
#include
+#include
+#endif
#include
#include
#include
@@ -36,38 +49,25 @@
#include "pxr/base/arch/systemInfo.h"
#include "pxr/base/arch/error.h"
+#include "pxr/base/arch/fileSystem.h"
#if defined(ARCH_OS_DARWIN)
#include
#include
#endif
-#ifdef _POSIX_VERSION
-#include /* for PATH_MAX */
-#else
-#include /* for MAXPATHLEN */
-#endif
-
-#ifndef PATH_MAX
-#ifdef _POSIX_VERSION
-#define PATH_MAX _POSIX_PATH_MAX
-#else
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-#endif
-
-using std::string;
+using namespace std;
string
ArchGetCwd()
{
- char space[4096];
- if (getcwd(space, 4096))
- return string(space);
-
+#if defined(ARCH_OS_WINDOWS)
+ char space[ARCH_PATH_MAX];
+ if (::_getcwd(space, ARCH_PATH_MAX))
+ return string(space);
+#else
+ char space[4096];
+ if (getcwd(space, 4096))
+ return string(space);
#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN)
@@ -90,7 +90,7 @@ ArchGetCwd()
#else
#error Unknown architecture.
#endif
-
+#endif
ARCH_WARNING("can't determine working directory");
return ".";
}
@@ -98,8 +98,15 @@ ArchGetCwd()
string
ArchGetHomeDirectory(const std::string &login)
{
+#if defined(ARCH_OS_WINDOWS)
+ char path[ARCH_PATH_MAX];
+ if (SUCCEEDED(::SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, path)))
+ {
+ return string(path);
+ }
+#else
if (login.empty()) {
- const char* home = getenv("HOME");
+ const char* home = ArchGetEnv("HOME");
if (home && home[0] != '\0')
return home;
}
@@ -118,7 +125,7 @@ ArchGetHomeDirectory(const std::string &login)
: getpwnam_r(login.c_str(), pwdPtr, buf, sizeof(buf), &tmpPtr);
if (result == 0 and tmpPtr)
return pwd.pw_dir;
-
+#endif
return "";
}
@@ -127,12 +134,19 @@ ArchGetUserName()
{
const char* envVarNames[] = {"LOGNAME", "USER", "LNAME", "USERNAME"};
for (size_t i = 0; i < sizeof(envVarNames) / sizeof(*envVarNames); ++i) {
- if (const char* user = getenv(envVarNames[i])) {
+ if (const char* user = ArchGetEnv(envVarNames[i])) {
if (user && user[0] != '\0')
return user;
}
}
+#if defined(ARCH_OS_WINDOWS)
+ char name [UNLEN + 1];
+ DWORD size = UNLEN + 1;
+
+ if (!::GetUserName(name, &size))
+ return string(name);
+#else
// Convert the effective user ID into a string. If we can't do it,
// fall back to user name.
char buffer[2048];
@@ -140,7 +154,7 @@ ArchGetUserName()
if (getpwuid_r(geteuid(), &pwd, buffer, sizeof(buffer), &resultPwd) == 0)
return pwd.pw_name;
-
+#endif
return "";
}
@@ -165,9 +179,25 @@ ArchGetExecutablePath()
linebuffer[0] = 0;
_NSGetExecutablePath(linebuffer, &bufsize);
return linebuffer;
+#elif defined(ARCH_OS_WINDOWS)
+ char path[ARCH_PATH_MAX];
+ if (::GetModuleFileName(NULL, path, ARCH_PATH_MAX))
+ return string(path);
+ return string();
#else
#error Unknown architecture.
#endif
}
+
+size_t ArchGetPageSize()
+{
+#if defined(ARCH_OS_WINDOWS)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+#else
+ return sysconf(_SC_PAGESIZE);
+#endif
+}
\ No newline at end of file
diff --git a/pxr/base/lib/arch/systemInfo.h b/pxr/base/lib/arch/systemInfo.h
index fb1c79ff5b..ef9a548e01 100644
--- a/pxr/base/lib/arch/systemInfo.h
+++ b/pxr/base/lib/arch/systemInfo.h
@@ -24,45 +24,49 @@
#ifndef ARCH_SYSTEMINFO_H
#define ARCH_SYSTEMINFO_H
+/// \file arch/systemInfo.h
+/// \ingroup group_arch_SystemFunctions
+/// Provide architecture-specific system information.
+
+#include "pxr/base/arch/api.h"
+#include
#include
-/*!
- * \file systemInfo.h
- * \brief Provide architecture-specific system information.
- * \ingroup group_arch_SystemFunctions
- */
+/// \addtogroup group_arch_SystemFunctions
+///@{
-/*!
- * \brief Return current working directory as a string.
- * \ingroup group_arch_SystemFunctions
- */
+/// Return current working directory as a string.
+ARCH_API
std::string ArchGetCwd();
-/*!
- * \brief Return user's home directory.
- * \ingroup group_arch_SystemFunctions
- *
- * If \p login is not supplied, the home directory of the current user is
- * returned. Otherwise, the home directory of the user with the specified
- * login is returned. If the home directory cannot be determined, the empty
- * string is returned.
- */
+/// Return user's home directory.
+///
+/// If \p login is not supplied, the home directory of the current user is
+/// returned. Otherwise, the home directory of the user with the specified
+/// login is returned. If the home directory cannot be determined, the empty
+/// string is returned.
+ARCH_API
std::string ArchGetHomeDirectory(const std::string &login = std::string());
-/*!
- * \brief Return user name.
- * \ingroup group_arch_SystemFunctions
- *
- * If the user name cannot determined, the empty string is returned.
- */
+/// Return user name.
+///
+/// If the user name cannot determined, the empty string is returned.
+ARCH_API
std::string ArchGetUserName();
-/*!
- * \brief Return the path to the program's executable.
- * \ingroup group_arch_SystemFunctions
- *
- * Return the path of the executing binary.
- */
+/// Return the path to the program's executable.
+ARCH_API
std::string ArchGetExecutablePath();
+///@}
+
+/*!
+* \brief Get memory page size.
+* \ingroup group_arch_SystemFunctions
+*
+* Return the memory page size.
+*/
+ARCH_API
+size_t ArchGetPageSize();
+
#endif // ARCH_SYSTEMINFO_H
diff --git a/pxr/base/lib/arch/testArchAbi.h b/pxr/base/lib/arch/testArchAbi.h
index 9117ab0014..783445cac8 100644
--- a/pxr/base/lib/arch/testArchAbi.h
+++ b/pxr/base/lib/arch/testArchAbi.h
@@ -22,8 +22,11 @@
// language governing permissions and limitations under the Apache License.
//
#if defined(_WIN32)
+#include "pxr/base/arch/defines.h"
+
+#if defined(ARCH_OS_WINDOWS)
#ifndef ARCH_ABI_API
-#define ARCH_ABI_API __declspec(dllimport)
+#define ARCH_ABI_API ARCH_EXPORT
#endif
#else
#define ARCH_ABI_API __attribute__((visibility("default")))
diff --git a/pxr/base/lib/arch/testenv/testArchAbi.cpp b/pxr/base/lib/arch/testenv/testArchAbi.cpp
index 11d56bcd72..9ac0cbf883 100644
--- a/pxr/base/lib/arch/testenv/testArchAbi.cpp
+++ b/pxr/base/lib/arch/testenv/testArchAbi.cpp
@@ -21,14 +21,16 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/library.h"
#include "pxr/base/arch/testArchAbi.h"
#include "pxr/base/arch/systemInfo.h"
#include "pxr/base/arch/vsnprintf.h"
#include
#include
#include
-#ifdef _WIN32
-#include
+#include
+#ifdef ARCH_OS_WINDOWS
+#include
#define GETSYM GetProcAddress
#else
#include
@@ -43,8 +45,8 @@ main(int argc, char** argv)
{
// Load the plugin and get the factory function.
std::string error;
-#ifdef _WIN32
- HMODULE plugin = LoadLibrary(".\\libtestArchAbiPlugin.dll");
+#ifdef ARCH_OS_WINDOWS
+ HMODULE plugin = (HMODULE)ArchOpenLibrary(".\\libtestArchAbiPlugin.dll", ARCH_LIBRARY_LAZY);
if (not plugin) {
error = ArchStringPrintf("%ld", (long)GetLastError());
}
@@ -53,7 +55,7 @@ main(int argc, char** argv)
// Up two directories.
path = path.substr(0, path.rfind('/', path.rfind('/') - 1));
path += "/tests/lib/libtestArchAbiPlugin.so";
- void* plugin = dlopen(path.c_str(), RTLD_LAZY);
+ void* plugin = ArchOpenLibrary(path.c_str(), ARCH_LIBRARY_LAZY);
if (not plugin) {
error += dlerror();
}
diff --git a/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp b/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp
index 820d6e55f6..f74090d143 100644
--- a/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp
+++ b/pxr/base/lib/arch/testenv/testArchAbiPlugin.cpp
@@ -21,18 +21,13 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
+#include "pxr/base/arch/export.h"
#include "pxr/base/arch/testArchAbi.h"
#include
#include