Skip to content

Commit

Permalink
feat: query/print build information (AcademySoftwareFoundation#4124)
Browse files Browse the repository at this point in the history
New OIIO global attributes (read only):

- "build:platform" retrieves the OS and CPU type that this build of OIIO
is fof (e.g., "Linux/x86_64").
- "build:compiler" retrieves the compiler name and version used to build
OIIO itself (e.g. "gcc 9.3").
- "build:dependencies" retrieves a semicolon-separated list of library
dependencies -- both for image format support (like libtiff) but also
general (boost, TBB, Python, fmt, OCIO).
- "build:simd" is a new (preferred) synonym for the SIMD and other
hardware capabilities selected at build time. The old name, "oiio:simd"
is hereby softly deprecated as confusing.

`oiiotool --buildinfo` is a new command that prints this information.

Example output:

```
$ oiiotool --buildinfo

OIIO 2.6.0.2spi | MacOS/x86_64
    Build compiler: Apple clang 15.0 | C++17/201703
    HW features enabled at build: sse2,sse3,ssse3,sse41,sse42
Dependencies: OpenEXR 3.2.1, LIBTIFF Version 4.6.0, jpeg-turbo
    3.0.1/jp80, dcmtk 3.6.8, FFMpeg 6.0 (Lavf60.16.100), gif_lib 5.2.1,
    libheif 1.17.6, OpenJpeg 2.5.0, null 1.0, OpenVDB 11.0.0abi11, libpng
    1.6.40, Ptex 2.4, libraw 0.21.2-Release, Webp 1.3.2, Boost 1.83,
    OpenColorIO 2.3.1, Python 3.11.7, TBB 2021.11.0, fmt 10.2.1
```

This is all a convenience utility to make it easy to ask users to run a
simple command that will tell us a lot of information relevant to
resolving their issues in cases where it's related to some of their
build-time compiler or dependencies.

Also cleaned up the "bug report issue template" to clarify the
instructions and specifically ask people to run this command and include
the information with any bug report.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
  • Loading branch information
lgritz committed Jan 30, 2024
1 parent 4a9a5d3 commit 2491891
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 54 deletions.
35 changes: 23 additions & 12 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,40 @@ assignees: ''
---

**Describe the bug**

A clear and concise description of what the bug is. What happened, and
what did you expect to happen instead.


**OpenImageIO version and dependencies**

Please run `oiiotool --buildinfo` and paste the output here.

Also please tell us if there was anything unusual about your environment or
nonstandard build options you used.


**To Reproduce**

Steps to reproduce the behavior:
1. Do this...
2. Then this...
3. Then THIS happens (reproduce the exact error message if you can)
4. Whereas I expected this other specific thing to happen instead.

If the problem occurs in your C++ or Python code that uses the OIIO APIs, can
you also reproduce the problem using oiiotool? If so, please describe the
exact command line that reproduces the problem. (Being able to reproduce the
problem using only OIIO components makes it a lot easier for the developers
investigate and makes it clear it's not your application's fault.)

**Expected behavior**
A clear and concise description of what you expected to happen.

**Evidence**
Do you have error messages? (please quote exactly) Screenshots? Example
command lines or scripts that reliably reproduce the error? If it only
happens with certain image files, can you attach the smallest image you
can make that reproduces the problem?

**Platform information:**
- OIIO branch/version:
- OS:
- C++ compiler:
- Any non-default build flags when you build OIIO:

- Error messages (paste them here exactly)
- Screenshots (if helpful)
- Example input: If the problem only happens with certain image files, please
attach the smallest image you can make that reproduces the problem.


**IF YOU ALREADY HAVE A CODE FIX:** There is no need to file a separate issue,
Expand Down
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ include_directories (
# Tell CMake to process the sub-directories
add_subdirectory (src/libutil)

find_or_download_robin_map ()


# Add IO plugin directories -- if we are embedding plugins, we need to visit
Expand Down
12 changes: 11 additions & 1 deletion src/cmake/checked_find_package.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ set (OPTIONAL_DEPS "" CACHE STRING
"Additional dependencies to consider optional (semicolon-separated list, or ALL)")
option (ALWAYS_PREFER_CONFIG "Prefer a dependency's exported config file if it's available" OFF)

# Track all build deps we find with checked_find_package
set (CFP_ALL_BUILD_DEPS_FOUND "")

# Utility function to list the names and values of all variables matching
# the pattern (case-insensitive)
Expand Down Expand Up @@ -66,14 +68,17 @@ endfunction ()
# file from the package before using a FindPackage.cmake module.
# * Optional DEBUG turns on extra debugging information related to how
# this package is found.
# * Found package "name version" or "name NONE" are accumulated in the list
# CFP_ALL_BUILD_DEPS_FOUND. If the optional NO_RECORD_NOTFOUND is
# supplied, un-found packags will not be recorded.
#
# N.B. This needs to be a macro, not a function, because the find modules
# will set(blah val PARENT_SCOPE) and we need that to be the global scope,
# not merely the scope for this function.
macro (checked_find_package pkgname)
cmake_parse_arguments(_pkg # prefix
# noValueKeywords:
"REQUIRED;PREFER_CONFIG;DEBUG"
"REQUIRED;PREFER_CONFIG;DEBUG;NO_RECORD_NOTFOUND"
# singleValueKeywords:
"ENABLE;ISDEPOF;VERSION_MIN;VERSION_MAX;RECOMMEND_MIN;RECOMMEND_MIN_REASON"
# multiValueKeywords:
Expand Down Expand Up @@ -155,6 +160,8 @@ macro (checked_find_package pkgname)
message (STATUS "${ColorYellow}Recommend ${pkgname} >= ${_pkg_RECOMMEND_MIN} ${_pkg_RECOMMEND_MIN_REASON} ${ColorReset}")
endif ()
endif ()
string (STRIP "${pkgname} ${${pkgname}_VERSION}" app_)
list (APPEND CFP_ALL_BUILD_DEPS_FOUND "${app_}")
else ()
message (STATUS "${ColorRed}${pkgname} library not found ${ColorReset}")
if (${pkgname}_ROOT)
Expand All @@ -176,6 +183,9 @@ macro (checked_find_package pkgname)
if (_pkg_REQUIRED)
message (FATAL_ERROR "${ColorRed}${pkgname} is required, aborting.${ColorReset}")
endif ()
if (NOT _pkg_NO_RECORD_NOTFOUND)
list (APPEND CFP_ALL_BUILD_DEPS_FOUND "${pkgname} NONE")
endif ()
endif()
if (_pkg_VERBOSE AND (${pkgname}_FOUND OR ${pkgname_upper}_FOUND OR _pkg_DEBUG))
if (_pkg_DEBUG)
Expand Down
14 changes: 12 additions & 2 deletions src/cmake/externalpackages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ endif()
# From pythonutils.cmake
find_python()

checked_find_package (pybind11 REQUIRED VERSION_MIN 2.4.2)


###########################################################################
# Dependencies for optional formats and features. If these are not found,
Expand Down Expand Up @@ -249,12 +251,14 @@ if (NOT Ptex_FOUND OR NOT Ptex_VERSION)
endif ()

checked_find_package (WebP)
# Note: When WebP 1.1 (released late 2019) is our minimum, we can use their
# exported configs and remove our FindWebP.cmake module.

option (USE_R3DSDK "Enable R3DSDK (RED camera) support" OFF)
checked_find_package (R3DSDK) # RED camera
checked_find_package (R3DSDK NO_RECORD_NOTFOUND) # RED camera

set (NUKE_VERSION "7.0" CACHE STRING "Nuke version to target")
checked_find_package (Nuke)
checked_find_package (Nuke NO_RECORD_NOTFOUND)


# Qt -- used for iv
Expand Down Expand Up @@ -313,6 +317,8 @@ macro (find_or_download_robin_map)
checked_find_package (Robinmap REQUIRED)
endmacro()

find_or_download_robin_map ()


###########################################################################
# fmtlib
Expand Down Expand Up @@ -360,6 +366,7 @@ macro (find_or_download_fmt)
math(EXPR FMT_VERSION_MINOR "(${FMT_VERSION_NUMERIC} / 100) % 100")
math(EXPR FMT_VERSION_MAJOR "${FMT_VERSION_NUMERIC} / 10000")
set (fmt_VERSION "${FMT_VERSION_MAJOR}.${FMT_VERSION_MINOR}.${FMT_VERSION_PATCH}")
list (APPEND CFP_ALL_BUILD_DEPS_FOUND "${pkgname} ${${pkgname}_VERSION}")
else ()
get_target_property(FMT_INCLUDE_DIR fmt::fmt-header-only INTERFACE_INCLUDE_DIRECTORIES)
set (OIIO_USING_FMT_LOCAL FALSE)
Expand All @@ -374,3 +381,6 @@ if (fmt_VERSION VERSION_EQUAL 9.1.0
AND GCC_VERSION VERSION_GREATER 0.0 AND NOT GCC_VERSION VERSION_GREATER 7.2)
message (WARNING "${ColorRed}fmt 9.1 is known to not work with gcc <= 7.2${ColorReset}")
endif ()

list (SORT CFP_ALL_BUILD_DEPS_FOUND COMPARE STRING CASE INSENSITIVE)
message (STATUS "All build dependencies: ${CFP_ALL_BUILD_DEPS_FOUND}")
10 changes: 10 additions & 0 deletions src/cmake/modules/FindWebP.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
# definitions giving the version:
# WEBP_VERSION Version of Webp (e.g., 3.6.2)

# Try the config for newer WebP versions.
find_package(WebP CONFIG)

if (NOT TARGET WebP::webp)
# If not found, roll our own.
# Note: When WebP 1.1 (released late 2019) is our minimum, we can use their
# exported configs and remove our FindWebP.cmake module.

include (FindPackageHandleStandardArgs)

find_path (WEBP_INCLUDE_DIR webp/encode.h
Expand Down Expand Up @@ -65,3 +73,5 @@ mark_as_advanced (
WEBP_LIBRARY
WEBPDEMUX_LIBRARY
)

endif ()
5 changes: 5 additions & 0 deletions src/doc/oiiotool.rst
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,11 @@ output each one to a different file, with names `sub0001.tif`,
Print timing and memory statistics about the work done by
:program:`oiiotool`.

.. option:: --buildinfo

Print information about OIIO build-time options and dependencies.
This can be useful when reporting issues.

.. option:: -a

Performs all operations on all subimages and/or MIPmap levels of each
Expand Down
23 changes: 20 additions & 3 deletions src/include/OpenImageIO/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -3107,13 +3107,30 @@ inline bool attribute (string_view name, string_view val) {
/// (Added in OpenImageIO 2.5.2)
///
/// - `string hw:simd`
/// - `string oiio:simd` (read-only)
/// - `string build:simd` (read-only)
///
/// A comma-separated list of hardware CPU features for SIMD (and some
/// other things). The `"oiio:simd"` attribute is similarly a list of
/// other things). The `"build:simd"` attribute is similarly a list of
/// which features this build of OIIO was compiled to support.
///
/// This was added in OpenImageIO 1.8.
/// These were added in OpenImageIO 1.8. The `"build:simd"` attribute was
/// added added in OpenImageIO 2.5.8 as a preferred synonym for what
/// previously was called `"oiio:simd"`, which is now deprecated.
///
/// - `string build:platform` (read-only)
///
/// THe name of the OS and CPU architecture that OpenImageIO was built
/// for (e.g., `"Linux/x86_64"`). (Added in OpenImageIO 2.5.8.)
///
/// - `string build:compiler` (read-only)
///
/// THe name and version of the compiler used to build OIIO.
/// (Added in OpenImageIO 2.5.8.)
///
/// - `string build:dependencies` (read-only)
///
/// List of library dependencieis (where known) and versions, separatd by
/// semicolons. (Added in OpenImageIO 2.5.8.)
///
/// - `float resident_memory_used_MB`
///
Expand Down
16 changes: 11 additions & 5 deletions src/libOpenImageIO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ else ()
message (STATUS "OpenEXR core library will not be used by default")
endif ()

# Some extra definitions we need to retrieve build related attributes.
target_compile_definitions(OpenImageIO
PRIVATE
OIIO_FREETYPE_VERSION="${FREETYPE_VERSION_STRING}"
OIIO_OpenCV_VERSION="${OpenCV_VERSION}"
OIIO_PYTHON_VERSION="${Python_VERSION}"
OIIO_QT_VERSION="${Qt6_VERSION}${Qt5_VERSION}"
OIIO_TBB_VERSION="${TBB_VERSION}"
)

# Source groups for libutil and libtexture
source_group ("libutil" REGULAR_EXPRESSION ".+/libutil/.+")
source_group ("libtexture" REGULAR_EXPRESSION ".+/libtexture/.+")
Expand All @@ -126,7 +136,6 @@ target_include_directories (OpenImageIO
${OPENEXR_INCLUDES}
PRIVATE
${ROBINMAP_INCLUDES}
${FREETYPE_INCLUDE_DIRS}
)
target_include_directories (OpenImageIO SYSTEM PUBLIC ${OpenCV_INCLUDES})

Expand All @@ -151,16 +160,13 @@ target_link_libraries (OpenImageIO
$<TARGET_NAME_IF_EXISTS:OpenColorIO::OpenColorIOHeaders>
$<TARGET_NAME_IF_EXISTS:pugixml::pugixml>
$<TARGET_NAME_IF_EXISTS:TBB::tbb>
$<TARGET_NAME_IF_EXISTS:Freetype::Freetype>
${BZIP2_LIBRARIES}
ZLIB::ZLIB
$<TARGET_NAME_IF_EXISTS:Boost::thread>
${CMAKE_DL_LIBS}
)

if (FREETYPE_FOUND)
target_link_libraries (OpenImageIO PRIVATE ${FREETYPE_LIBRARIES})
endif()

if (WIN32)
target_link_libraries (OpenImageIO PRIVATE psapi)
endif()
Expand Down
73 changes: 72 additions & 1 deletion src/libOpenImageIO/imageio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,64 @@ oiio_simd_caps()
// clang-format on
}


static std::string
oiio_build_compiler()
{
using Strutil::fmt::format;

std::string comp;
#if OIIO_GNUC_VERSION
comp = format("gcc {}.{}", __GNUC__, __GNUC_MINOR__);
#elif OIIO_CLANG_VERSION
comp = format("clang {}.{}", __clang_major__, __clang_minor__);
#elif OIIO_APPLE_CLANG_VERSION
comp = format("Apple clang {}.{}", __clang_major__, __clang_minor__);
#elif OIIO_INTEL_COMPILER
comp = format("Intel icc {}", OIIO_INTEL_CLASSIC_COMPILER_VERSION);
#elif OIIO_INTEL_LLVM_COMPILER
comp = format("Intel icx {}.{}", __clang_major__, __clang_minor__);
#elif OIIO_MSVS_VERSION
comp = format("MSVS {}", OIIO_MSVS_VERSION);
#else
comp = "unknown compiler?";
#endif
return comp;
}


static std::string
oiio_build_platform()
{
std::string platform;
#if defined(__LINUX__)
platform = "Linux";
#elif defined(__APPLE__)
platform = "MacOS";
#elif defined(_WIN32)
platform = "Windows";
#elif defined(__MINGW32__)
platform = "MinGW";
#elif defined(__FreeBSD__)
platform = "FreeBSD";
#else
platform = "UnknownOS";
#endif
platform += "/";
#if defined(__x86_64__)
platform += "x86_64";
#elif defined(__i386__)
platform += "i386";
#elif defined(_M_ARM64) || defined(__aarch64__) || defined(__aarch64)
platform += "ARM";
#else
platform = "unknown arch?";
#endif
return platform;
}



void
shutdown()
{
Expand Down Expand Up @@ -417,6 +475,7 @@ attribute(string_view name, TypeDesc type, const void* val)
bool
getattribute(string_view name, TypeDesc type, void* val)
{
using Strutil::fmt::format;
if (name == "threads" && type == TypeInt) {
*(int*)val = oiio_threads;
return true;
Expand Down Expand Up @@ -540,10 +599,22 @@ getattribute(string_view name, TypeDesc type, void* val)
*(ustring*)val = ustring(hw_simd_caps());
return true;
}
if (name == "oiio:simd" && type == TypeString) {
if ((name == "build:simd" || name == "oiio:simd") && type == TypeString) {
*(ustring*)val = ustring(oiio_simd_caps());
return true;
}
if (name == "build:compiler" && type == TypeString) {
*(ustring*)val = ustring(oiio_build_compiler());
return true;
}
if (name == "build:platform" && type == TypeString) {
*(ustring*)val = ustring(oiio_build_platform());
return true;
}
if (name == "build:dependencies" && type == TypeString) {
*(ustring*)val = ustring(OIIO_ALL_BUILD_DEPS_FOUND);
return true;
}
if (name == "resident_memory_used_MB" && type == TypeInt) {
*(int*)val = int(Sysutil::memory_used(true) >> 20);
return true;
Expand Down
3 changes: 3 additions & 0 deletions src/libOpenImageIO/imageio_pvt.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,7 @@ OIIO_NAMESPACE_END
//Define a default plugin search path
#define OIIO_DEFAULT_PLUGIN_SEARCHPATH "@PLUGIN_SEARCH_PATH_NATIVE@"

// List of build-time dependencies (semicolon separated)
#define OIIO_ALL_BUILD_DEPS_FOUND "@CFP_ALL_BUILD_DEPS_FOUND@"

#endif // OPENIMAGEIO_IMAGEIO_PVT_H
Loading

0 comments on commit 2491891

Please sign in to comment.