diff options
Diffstat (limited to 'tests')
26 files changed, 1668 insertions, 1336 deletions
| diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 75fb99c..d58791c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,5 @@ +# instructions - see ../doc/testing.txt +  cmake_minimum_required(VERSION 2.8)  if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)    # Explicitly use new include policy to avoid globally shadowing included modules @@ -10,7 +12,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")  # Build debug build as default  if(NOT CMAKE_BUILD_TYPE) -  set(CMAKE_BUILD_TYPE Debug) +  set(CMAKE_BUILD_TYPE RelWithDebInfo)  endif()  if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") @@ -27,11 +29,7 @@ endif()  if(WIN32_STATIC_BUILD)    if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") -    set(EMSG "\nTo build Win32 STATIC OpenSCAD tests you must run") -    set(EMSG "${EMSG} \ncmake .. -DCMAKE_BUILD_TYPE=Release") -    set(EMSG "${EMSG} \nthen replace /MD with /MT in CMakeCache.txt") -    set(EMSG "${EMSG} \ni.e. sed -i s/\\/MD/\\/MT/ CMakeCache.txt")  -    set(EMSG "${EMSG} \nthen re-run cmake ..")  +    set(EMSG "\nTo build Win32 STATIC OpenSCAD please see doc/testing.txt")      message(FATAL_ERROR ${EMSG})    endif()  endif() @@ -61,38 +59,45 @@ if(WIN32)    # you have to pass -DCMAKE_VERBOSE_MAKEFILE=ON to cmake when you run it.   endif() -  #  # Build test apps  #  # Boost -# -# usually it's found automatically, but some systems may need a custom install. -# in that case, run cmake with -DBOOST_ROOT=/path/to/boost/install -# (being the same path you passed to boost's --prefix when you built it) -if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "") -  set(BOOST_ROOT "$ENV{MACOSX_DEPLOY_DIR}") +if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") +  set(BOOST_ROOT "$ENV{OPENSCAD_LIBRARIES}")  endif() -if(BOOST_ROOT) -  #set(Boost_DEBUG TRUE) -  set(Boost_NO_SYSTEM_PATHS TRUE) -  set(Boost_ADDITIONAL_VERSIONS "1.47.0") -  find_package( Boost 1.35.0 COMPONENTS thread program_options filesystem system regex ) -  if(Boost_FOUND) -    message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS}) -    message(STATUS "Boost libraries found:") -    foreach(boostlib ${Boost_LIBRARIES}) -      message(STATUS "  " ${boostlib}) -    endforeach() -    include_directories(${Boost_INCLUDE_DIRS}) -  else() -    message(STATUS "BOOST_ROOT:" ${BOOST_ROOT}) -    message(FATAL_ERROR "BOOST_ROOT specified but no boost found") -  endif() +if (NOT $ENV{BOOSTDIR} STREQUAL "") +  set(BOOST_DIR "$ENV{BOOSTDIR}") +endif() + +if (NOT ${BOOST_DIR} STREQUAL "") +  set(BOOST_ROOT ${BOOST_DIR}) +  message(STATUS "BOOST_ROOT: " ${BOOST_ROOT}) +  set(Boost_NO_SYSTEM_PATHS "TRUE") +  set(Boost_DEBUG TRUE) +endif() + + +if (WIN32) +  set(Boost_USE_STATIC_LIBS TRUE) +  set(BOOST_STATIC TRUE) +  set(BOOST_THREAD_USE_LIB TRUE) +endif() + +set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0") +find_package( Boost 1.35.0 COMPONENTS thread program_options filesystem system regex ) +if(Boost_FOUND) +  message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS}) +  message(STATUS "Boost libraries found:") +  foreach(boostlib ${Boost_LIBRARIES}) +    message(STATUS "  " ${boostlib}) +  endforeach() +  include_directories(${Boost_INCLUDE_DIRS})  else() -  message(STATUS "BOOST_ROOT unset. Assuming it will be found automatically.") +  message(STATUS "BOOST_ROOT: ${BOOST_ROOT}") +  message(FATAL_ERROR "Boost not found.")  endif()  # Mac OS X @@ -101,10 +106,20 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")  endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")  # Qt4 + +if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +  # make /usr/local/include/qt4 come before /usr/local/include (QT4 vs QT3) +  set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON) +endif() +  find_package(OpenGL)  find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)  include(${QT_USE_FILE}) +if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +  set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF) +endif() +  # Eigen2  # Turn off Eigen SIMD optimization @@ -117,11 +132,13 @@ endif()  if (NOT EIGEN2_INCLUDE_DIR)    find_path(EIGEN2_INCLUDE_DIR              Eigen/Core  -            PATHS ENV EIGEN2DIR /opt/local/include/eigen2 /usr/include/eigen2) +            HINTS $ENV{EIGEN2DIR} +            PATHS /opt/local/include/eigen2 /usr/include/eigen2)    if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")       find_path(EIGEN2_INCLUDE_DIR                 Eigen/Core  -              PATHS ENV EIGEN2DIR /usr/local/include/eigen2 ) +              HINTS $ENV{EIGEN2DIR} +              PATHS /usr/local/include/eigen2 )    endif()    if (NOT EIGEN2_INCLUDE_DIR)      message(FATAL_ERROR "Eigen2 not found") @@ -132,19 +149,19 @@ endif()  include_directories(${EIGEN2_INCLUDE_DIR})  # OpenCSG -if (NOT $ENV{OPENCSG_DIR} STREQUAL "") -  set(OPENCSG_DIR "$ENV{OPENCSG_DIR}") -elseif (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "") -  set(OPENCSG_DIR "$ENV{MACOSX_DEPLOY_DIR}") +if (NOT $ENV{OPENCSGDIR} STREQUAL "") +  set(OPENCSG_DIR "$ENV{OPENCSGDIR}") +elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") +  set(OPENCSG_DIR "$ENV{OPENSCAD_LIBRARIES}")  endif()  if (NOT OPENCSG_INCLUDE_DIR)    message(STATUS "OPENCSG_DIR: " ${OPENCSG_DIR})    find_path(OPENCSG_INCLUDE_DIR              opencsg.h -            PATHS ${OPENCSG_DIR}/include) +            HINTS ${OPENCSG_DIR}/include)    find_library(OPENCSG_LIBRARY                 opencsg -               PATHS ${OPENCSG_DIR}/lib) +               HINTS ${OPENCSG_DIR}/lib)    if (NOT OPENCSG_INCLUDE_DIR OR NOT OPENCSG_LIBRARY)      message(FATAL_ERROR "OpenCSG not found")    else() @@ -156,8 +173,10 @@ include_directories(${OPENCSG_INCLUDE_DIR})  # GLEW -if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "") -  set(GLEW_DIR "$ENV{MACOSX_DEPLOY_DIR}") +if (NOT $ENV{GLEWDIR} STREQUAL "") +  set(GLEW_DIR "$ENV{GLEWDIR}") +elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") +  set(GLEW_DIR "$ENV{OPENSCAD_LIBRARIES}")  endif()  find_package(GLEW REQUIRED) @@ -185,16 +204,35 @@ BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_y  ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser)  set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX") -if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "") -  set(CGAL_DIR "$ENV{MACOSX_DEPLOY_DIR}/lib/CGAL") +# CGAL + +if (NOT $ENV{CGALDIR} STREQUAL "") +  set(CGAL_DIR "$ENV{CGALDIR}") +elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") +  set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")    set(CMAKE_MODULE_PATH "${CGAL_DIR}")  endif() +message(STATUS "CGAL_DIR: " ${CGAL_DIR})  find_package(CGAL REQUIRED) +message(STATUS "CGAL config found in " ${CGAL_USE_FILE} ) +foreach(cgal_incdir ${CGAL_INCLUDE_DIRS}) +  message(STATUS "CGAL include found in " ${cgal_incdir} ) +endforeach() +message(STATUS "CGAL libraries found in " ${CGAL_LIBRARIES_DIR} )  if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)    message(FATAL_ERROR "CGAL >= 3.6 required")  endif()  include_directories(${CGAL_INCLUDE_DIRS}) +# Imagemagick + +find_package(ImageMagick COMPONENTS convert) +if (ImageMagick_convert_FOUND) +  message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE}) +else() +  message(FATAL_ERROR "Couldn't find imagemagick 'convert' program") +endif() +  # Internal includes  include_directories(../src) @@ -239,15 +277,14 @@ set(NOCGAL_SOURCES  set(CGAL_SOURCES    ${NOCGAL_SOURCES} -  ../src/CSGTermEvaluator.cc  +	  ../src/CSGTermEvaluator.cc     ../src/CGAL_Nef_polyhedron.cc     ../src/cgalutils.cc     ../src/CGALEvaluator.cc    ../src/CGALCache.cc    ../src/PolySetCGALEvaluator.cc    ../src/CGAL_Nef_polyhedron_DxfData.cc -  ../src/cgaladv_minkowski2.cc -  ../src/cgaladv_convexhull2.cc) +  ../src/cgaladv_minkowski2.cc)  set(COMMON_SOURCES    ../src/nodedumper.cc  @@ -262,13 +299,13 @@ set(COMMON_SOURCES  #  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")  	message(STATUS "Offscreen OpenGL Context - using Apple CGL") -	set(OFFSCREEN_CTX_SOURCE "OffscreenContext.mm") +	set(OFFSCREEN_CTX_SOURCE "OffscreenContext.mm" CACHE TYPE STRING)  elseif(UNIX)  	message(STATUS "Offscreen OpenGL Context - using Unix GLX") -	set(OFFSCREEN_CTX_SOURCE "OffscreenContext.cc") +	set(OFFSCREEN_CTX_SOURCE "OffscreenContextGLX.cc" CACHE TYPE STRING)  elseif(WIN32)  	message(STATUS "Offscreen OpenGL Context - using Microsoft WGL") -	set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc") +	set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc" CACHE TYPE STRING)  endif()  set(OFFSCREEN_SOURCES @@ -287,6 +324,7 @@ target_link_libraries(tests-cgal tests-common)  add_library(tests-nocgal STATIC ${NOCGAL_SOURCES})  target_link_libraries(tests-nocgal tests-common)  add_library(tests-offscreen STATIC ${OFFSCREEN_SOURCES}) +# set_target_properties(tests-offscreen PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")  #  # echotest @@ -295,11 +333,6 @@ add_executable(echotest echotest.cc)  target_link_libraries(echotest tests-nocgal tests-core ${QT_LIBRARIES} ${OPENGL_LIBRARY} ${Boost_LIBRARIES})  # -# Yangli Hector Yee's PerceptualDiff code -# FIXME: Disabled since we use ImageMagick now. Eventually remove this and the files. -# add_executable(yee_compare yee_compare.cpp lodepng.cpp) - -#  # dumptest  #  add_executable(dumptest dumptest.cc) @@ -327,7 +360,7 @@ target_link_libraries(cgaltest tests-cgal ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRA  #  # cgalpngtest  # -add_executable(cgalpngtest cgalpngtest.cc bboxhelp.cc ../src/CGALRenderer.cc) +add_executable(cgalpngtest cgalpngtest.cc bboxhelp.cc ../src/CGALRenderer.cc ../src/renderer.cc ../src/rendersettings.cc)  set_target_properties(cgalpngtest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")  target_link_libraries(cgalpngtest tests-offscreen tests-cgal ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES}  ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY} ${Boost_LIBRARIES}) @@ -335,7 +368,7 @@ target_link_libraries(cgalpngtest tests-offscreen tests-cgal ${CGAL_LIBRARY} ${C  # opencsgtest  # -add_executable(opencsgtest opencsgtest.cc csgtestcore.cc ../src/OpenCSGRenderer.cc ../src/ThrownTogetherRenderer.cc) +add_executable(opencsgtest opencsgtest.cc csgtestcore.cc ../src/OpenCSGRenderer.cc ../src/ThrownTogetherRenderer.cc ../src/renderer.cc ../src/rendersettings.cc)  set_target_properties(opencsgtest PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")  target_link_libraries(opencsgtest tests-offscreen tests-cgal ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENCSG_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY} ${Boost_LIBRARIES}) @@ -343,7 +376,7 @@ target_link_libraries(opencsgtest tests-offscreen tests-cgal ${CGAL_LIBRARY} ${C  # throwntogethertest  # -add_executable(throwntogethertest throwntogethertest.cc csgtestcore.cc ../src/OpenCSGRenderer.cc ../src/ThrownTogetherRenderer.cc) +add_executable(throwntogethertest throwntogethertest.cc csgtestcore.cc ../src/OpenCSGRenderer.cc ../src/ThrownTogetherRenderer.cc ../src/renderer.cc ../src/rendersettings.cc)  set_target_properties(throwntogethertest PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")  target_link_libraries(throwntogethertest tests-offscreen tests-cgal ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENCSG_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY} ${Boost_LIBRARIES}) @@ -407,6 +440,12 @@ function(get_test_fullname TESTCMD FILENAME FULLNAME)    set(${FULLNAME} ${${FULLNAME}} PARENT_SCOPE)  endfunction() +# comparison method to use +if (NOT $ENV{COMPARATOR} STREQUAL "") +  set(COMPARATOR "$ENV{COMPARATOR}") +endif() +message(STATUS "COMPARATOR: " ${COMPARATOR}) +  #  # This functions adds cmd-line tests given files.  # Files are sent as the parameters following TESTSUFFIX @@ -437,13 +476,30 @@ macro(add_cmdline_test TESTCMD TESTSUFFIX)        set(CONFARG CONFIGURATIONS)        set(CONFVAL ${FOUNDCONFIGS}) -      add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}") +      add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py --comparator=${COMPARATOR} -c ${ImageMagick_convert_EXECUTABLE} -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")      endif()    endforeach()  endmacro()  enable_testing() +# set up custom pretty printing of results + +set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)") +set(PRETTYCMD "\"${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_pretty_print.py --builddir=${CMAKE_CURRENT_BINARY_DIR}\"") +set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake) +set(CTEST_CUSTOM_TXT "\n +  message(\"running 'opencsgtest --info' to generate sysinfo.txt\")\n +  ${INFOCMD}\n +  set(CTEST_CUSTOM_POST_TEST ${PRETTYCMD})\n +") +file(WRITE ${CTEST_CUSTOM_FILE} ${CTEST_CUSTOM_TXT}) + +foreach(FILE test_pretty_print.py) +  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILE} +                 ${CMAKE_CURRENT_BINARY_DIR}/${FILE} COPYONLY) +endforeach() +  set_directory_properties(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_SOURCE_DIR}/EnforceConfig.cmake")  # Find all scad files @@ -493,6 +549,9 @@ disable_tests(dumptest_transform-tests  # Reenable it when this is improved  disable_tests(opencsgtest_child-background) +# FIXME: This single test takes over an hour to run on a 2.7 GHz P4 +disable_tests(opencsgtest_example006 cgalpngtest_example006) +  # These tests only makes sense in OpenCSG mode  disable_tests(cgalpngtest_child-background                cgalpngtest_highlight-and-background-modifier diff --git a/tests/FindBoost.cmake b/tests/FindBoost.cmake index dfaf660..ea60354 100644 --- a/tests/FindBoost.cmake +++ b/tests/FindBoost.cmake @@ -17,8 +17,9 @@  #  # == Using actual libraries from within Boost: ==  # -#   set(Boost_USE_STATIC_LIBS   ON) -#   set(Boost_USE_MULTITHREADED ON) +#   set(Boost_USE_STATIC_LIBS        ON) +#   set(Boost_USE_MULTITHREADED      ON) +#   set(Boost_USE_STATIC_RUNTIME    OFF)  #   find_package( Boost 1.36.0 COMPONENTS date_time filesystem system ... )  #  #   if(Boost_FOUND) @@ -33,7 +34,7 @@  # Boost that contain header files only (e.g. foreach) you do not need to  # specify COMPONENTS.  # -# You should provide a minimum version number that should be used. If you provide this  +# You should provide a minimum version number that should be used. If you provide this  # version number and specify the REQUIRED attribute, this module will fail if it  # can't find the specified or a later version. If you specify a version number this is  # automatically put into the considered list of version numbers and thus doesn't need @@ -63,14 +64,15 @@  # Currently this module searches for the following version numbers:  # 1.33, 1.33.0, 1.33.1, 1.34, 1.34.0, 1.34.1, 1.35, 1.35.0, 1.35.1,  # 1.36, 1.36.0, 1.36.1, 1.37, 1.37.0, 1.38, 1.38.0, 1.39, 1.39.0, -# 1.40, 1.40.0, 1.41, 1.41.0 +# 1.40, 1.40.0, 1.41, 1.41.0, 1.42, 1.42.0, 1.43, 1.43.0, 1.44, 1.44.0, +# 1.45, 1.45.0, 1.46, 1.46.0, 1.46.1, 1.47, 1.47.0, 1.48, 1.48.0  #  # NOTE: If you add a new major 1.x version in Boost_ADDITIONAL_VERSIONS you should  # add both 1.x and 1.x.0 as shown above.  Official Boost include directories  # omit the 3rd version number from include paths if it is 0 although not all  # binary Boost releases do so.  # -# SET(Boost_ADDITIONAL_VERSIONS "1.78" "1.78.0" "1.79" "1.79.0") +# set(Boost_ADDITIONAL_VERSIONS "1.78" "1.78.0" "1.79" "1.79.0")  #  # ===================================== ============= ========================  # @@ -84,6 +86,43 @@  #   Boost_USE_STATIC_LIBS        Can be set to ON to force the use of the static  #                                boost libraries. Defaults to OFF.  # +#   Boost_NO_SYSTEM_PATHS        Set to TRUE to suppress searching in system +#                                paths (or other locations outside of BOOST_ROOT +#                                or BOOST_INCLUDEDIR).  Useful when specifying +#                                BOOST_ROOT. Defaults to OFF. +#                                  [Since CMake 2.8.3] +# +#   Boost_NO_BOOST_CMAKE         Do not do a find_package call in config mode +#                                before searching for a regular boost install. +#                                This will avoid finding boost-cmake installs. +#                                Defaults to OFF. +#                                  [Since CMake 2.8.6] +# +#   Boost_USE_STATIC_RUNTIME     If enabled, searches for boost libraries +#                                linked against a static C++ standard library +#                                ('s' ABI tag). This option should be set to +#                                ON or OFF because the default behavior +#                                if not specified is platform dependent +#                                for backwards compatibility. +#                                  [Since CMake 2.8.3] +# +#   Boost_USE_DEBUG_PYTHON       If enabled, searches for boost libraries +#                                compiled against a special debug build of +#                                Python ('y' ABI tag). Defaults to OFF. +#                                  [Since CMake 2.8.3] +# +#   Boost_USE_STLPORT            If enabled, searches for boost libraries +#                                compiled against the STLPort standard +#                                library ('p' ABI tag). Defaults to OFF. +#                                  [Since CMake 2.8.3] +# +#   Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS +#                                If enabled, searches for boost libraries +#                                compiled against the deprecated STLPort +#                                "native iostreams" feature ('n' ABI tag). +#                                Defaults to OFF. +#                                  [Since CMake 2.8.3] +#  # Other Variables used by this module which you may want to set.  #  #   Boost_ADDITIONAL_VERSIONS    A list of version numbers to use for searching @@ -101,17 +140,58 @@  #                                unless this is set to TRUE or the REQUIRED  #                                keyword is specified in find_package().  #                                  [Since CMake 2.8.0] -#  +#  #   Boost_COMPILER               Set this to the compiler suffix used by Boost  #                                (e.g. "-gcc43") if FindBoost has problems finding  #                                the proper Boost installation  # +#   Boost_THREADAPI                When building boost.thread, sometimes the name of the +#                                library contains an additional "pthread" or "win32" +#                                string known as the threadapi.  This can happen when +#                                compiling against pthreads on Windows or win32 threads +#                                on Cygwin.  You may specify this variable and if set +#                                when FindBoost searches for the Boost threading library +#                                it will first try to match the threadapi you specify. +#                                  For Example: libboost_thread_win32-mgw45-mt-1_43.a +#                                might be found if you specified "win32" here before +#                                falling back on libboost_thread-mgw45-mt-1_43.a. +#                                  [Since CMake 2.8.3] +# +#   Boost_REALPATH               Resolves symbolic links for discovered boost libraries +#                                to assist with packaging.  For example, instead of +#                                Boost_SYSTEM_LIBRARY_RELEASE being resolved to +#                                "/usr/lib/libboost_system.so" it would be +#                                "/usr/lib/libboost_system.so.1.42.0" instead. +#                                This does not affect linking and should not be +#                                enabled unless the user needs this information. +#                                  [Since CMake 2.8.3] +# + + +#  # These last three variables are available also as environment variables: +# Also, note they are completely UPPERCASE, except Boost_DIR.  # -#   BOOST_ROOT or BOOSTROOT      The preferred installation prefix for searching for -#                                Boost.  Set this if the module has problems finding +#   Boost_DIR or                 The preferred installation prefix for searching for +#   BOOST_ROOT or BOOSTROOT      Boost.  Set this if the module has problems finding  #                                the proper Boost installation.  # +#                                Note that Boost_DIR behaves exactly as <package>_DIR +#                                variables are documented to behave in find_package's +#                                Config mode.  That is, if it is set as a -D argument +#                                to CMake, it must point to the location of the +#                                BoostConfig.cmake or Boost-config.cmake file.  If it +#                                is set as an environment variable, it must point to +#                                the root of the boost installation.  BOOST_ROOT and +#                                BOOSTROOT, on the other hand, will point to the root +#                                in either case. +# +#                                To prevent falling back on the system paths, set +#                                Boost_NO_SYSTEM_PATHS to true. +# +#                                To avoid finding boost-cmake installations, set +#                                Boost_NO_BOOST_CMAKE to true. +#  #   BOOST_INCLUDEDIR             Set this to the include directory of Boost, if the  #                                module has problems finding the proper Boost installation  # @@ -165,7 +245,7 @@  # Copyright 2007      Wengo  # Copyright 2007      Mike Jackson  # Copyright 2008      Andreas Pakulat <apaku@gmx.de> -# Copyright 2008-2009 Philip Lowman <philip@yhbt.com> +# Copyright 2008-2010 Philip Lowman <philip@yhbt.com>  #  # Distributed under the OSI-approved BSD License (the "License");  # see accompanying file Copyright.txt for details. @@ -174,9 +254,46 @@  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  # See the License for more information.  #============================================================================= -# (To distributed this file outside of CMake, substitute the full +# (To distribute this file outside of CMake, substitute the full  #  License text for the above reference.) + +#------------------------------------------------------------------------------- +# Before we go searching, check whether boost-cmake is avaialble, unless the +# user specifically asked NOT to search for boost-cmake. +# +# If Boost_DIR is set, this behaves as any find_package call would. If not, +# it looks at BOOST_ROOT and BOOSTROOT to find Boost. +# +if (NOT Boost_NO_BOOST_CMAKE) +  # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, +  # since these are more conventional for Boost. +  if ("$ENV{Boost_DIR}" STREQUAL "") +    if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") +      set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) +    elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") +      set(ENV{Boost_DIR} $ENV{BOOSTROOT}) +    endif() +  endif() + +  # Do the same find_package call but look specifically for the CMake version. +  # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no +  # need to delegate them to this find_package call. +  find_package(Boost QUIET NO_MODULE) + +  # If we found boost-cmake, then we're done.  Print out what we found. +  # Otherwise let the rest of the module try to find it. +  if (Boost_FOUND) +    message("Boost ${Boost_FIND_VERSION} found.") +    if (Boost_FIND_COMPONENTS) +      message("Found Boost components:") +      message("   ${Boost_FIND_COMPONENTS}") +    endif() +    return() +  endif() +endif() + +  #-------------------------------------------------------------------------------  #  FindBoost functions & macros  # @@ -192,59 +309,65 @@  # And ELSE/ENDIF pairs were removed for readability.  ######################################################################### -MACRO (_Boost_ADJUST_LIB_VARS basename) -  IF (Boost_INCLUDE_DIR ) -    IF (Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) +macro(_Boost_ADJUST_LIB_VARS basename) +  if(Boost_INCLUDE_DIR ) +    if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE)        # if the generator supports configuration types then set        # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value -      IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) -        SET(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) -      ELSE() +      if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) +        set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) +      else()          # if there are no configuration types and CMAKE_BUILD_TYPE has no value          # then just use the release libraries -        SET(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) -      ENDIF() +        set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) +      endif()        # FIXME: This probably should be set for both cases -      SET(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) -    ENDIF() +      set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) +    endif()      # if only the release version was found, set the debug variable also to the release version -    IF (Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) -      SET(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) -      SET(Boost_${basename}_LIBRARY       ${Boost_${basename}_LIBRARY_RELEASE}) -      SET(Boost_${basename}_LIBRARIES     ${Boost_${basename}_LIBRARY_RELEASE}) -    ENDIF() +    if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) +      set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) +      set(Boost_${basename}_LIBRARY       ${Boost_${basename}_LIBRARY_RELEASE}) +      set(Boost_${basename}_LIBRARIES     ${Boost_${basename}_LIBRARY_RELEASE}) +    endif()      # if only the debug version was found, set the release variable also to the debug version -    IF (Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) -      SET(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) -      SET(Boost_${basename}_LIBRARY         ${Boost_${basename}_LIBRARY_DEBUG}) -      SET(Boost_${basename}_LIBRARIES       ${Boost_${basename}_LIBRARY_DEBUG}) -    ENDIF() -     -    IF (Boost_${basename}_LIBRARY) +    if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) +      set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) +      set(Boost_${basename}_LIBRARY         ${Boost_${basename}_LIBRARY_DEBUG}) +      set(Boost_${basename}_LIBRARIES       ${Boost_${basename}_LIBRARY_DEBUG}) +    endif() + +    # If the debug & release library ends up being the same, omit the keywords +    if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG}) +      set(Boost_${basename}_LIBRARY   ${Boost_${basename}_LIBRARY_RELEASE} ) +      set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) +    endif() + +    if(Boost_${basename}_LIBRARY)        set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY} CACHE FILEPATH "The Boost ${basename} library")        # Remove superfluous "debug" / "optimized" keywords from        # Boost_LIBRARY_DIRS -      FOREACH(_boost_my_lib ${Boost_${basename}_LIBRARY}) -        GET_FILENAME_COMPONENT(_boost_my_lib_path "${_boost_my_lib}" PATH) -        LIST(APPEND Boost_LIBRARY_DIRS ${_boost_my_lib_path}) -      ENDFOREACH() -      LIST(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) +      foreach(_boost_my_lib ${Boost_${basename}_LIBRARY}) +        get_filename_component(_boost_my_lib_path "${_boost_my_lib}" PATH) +        list(APPEND Boost_LIBRARY_DIRS ${_boost_my_lib_path}) +      endforeach() +      list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS)        set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIRS} CACHE FILEPATH "Boost library directory") -      SET(Boost_${basename}_FOUND ON CACHE INTERNAL "Whether the Boost ${basename} library found") -    ENDIF(Boost_${basename}_LIBRARY) +      set(Boost_${basename}_FOUND ON CACHE INTERNAL "Whether the Boost ${basename} library found") +    endif(Boost_${basename}_LIBRARY) -  ENDIF (Boost_INCLUDE_DIR ) +  endif(Boost_INCLUDE_DIR )    # Make variables changeble to the advanced user -  MARK_AS_ADVANCED( +  mark_as_advanced(        Boost_${basename}_LIBRARY        Boost_${basename}_LIBRARY_RELEASE        Boost_${basename}_LIBRARY_DEBUG    ) -ENDMACRO (_Boost_ADJUST_LIB_VARS) +endmacro(_Boost_ADJUST_LIB_VARS)  #------------------------------------------------------------------------------- @@ -252,17 +375,17 @@ ENDMACRO (_Boost_ADJUST_LIB_VARS)  # Runs compiler with "-dumpversion" and parses major/minor  # version with a regex.  # -FUNCTION(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) +function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) -  EXEC_PROGRAM(${CMAKE_CXX_COMPILER} +  exec_program(${CMAKE_CXX_COMPILER}      ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion      OUTPUT_VARIABLE _boost_COMPILER_VERSION    ) -  STRING(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" +  string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"      _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION}) -  SET(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) -ENDFUNCTION() +  set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) +endfunction()  #  # A convenience function for marking desired components @@ -276,16 +399,45 @@ function(_Boost_MARK_COMPONENTS_FOUND _yes_or_no)  endfunction()  # +# Take a list of libraries with "thread" in it +# and prepend duplicates with "thread_${Boost_THREADAPI}" +# at the front of the list +# +function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) +  set(_orig_libnames ${ARGN}) +  string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames ${_orig_libnames}) +  set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) +endfunction() + +# +# If a library is found, replace its cache entry with its REALPATH +# +function(_Boost_SWAP_WITH_REALPATH _library _docstring) +  if(${_library}) +    get_filename_component(_boost_filepathreal ${${_library}} REALPATH) +    unset(${_library} CACHE) +    set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") +  endif() +endfunction() + +function(_Boost_CHECK_SPELLING _var) +  if(${_var}) +    string(TOUPPER ${_var} _var_UC) +    message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling.  The proper spelling is ${_var_UC}.") +  endif() +endfunction() + +#  # End functions/macros -#   +#  #------------------------------------------------------------------------------- -IF(NOT DEFINED Boost_USE_MULTITHREADED) -    SET(Boost_USE_MULTITHREADED TRUE) -ENDIF() +if(NOT DEFINED Boost_USE_MULTITHREADED) +    set(Boost_USE_MULTITHREADED TRUE) +endif()  if(Boost_FIND_VERSION_EXACT)    # The version may appear in a directory with or without the patch @@ -297,6 +449,8 @@ else(Boost_FIND_VERSION_EXACT)    # The user has not requested an exact version.  Among known    # versions, find those that are acceptable to the user request.    set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} +    "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" +    "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42"      "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37"      "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0"      "1.34" "1.33.1" "1.33.0" "1.33") @@ -325,49 +479,47 @@ endif(Boost_FIND_VERSION_EXACT)  # Boost.  set(Boost_ERROR_REASON) -SET( _boost_IN_CACHE TRUE) -IF(Boost_INCLUDE_DIR) +set( _boost_IN_CACHE TRUE) +if(Boost_INCLUDE_DIR)    # On versions < 1.35, remove the System library from the considered list    # since it wasn't added until 1.35.    if(Boost_VERSION AND Boost_FIND_COMPONENTS) -     math(EXPR _boost_maj "${Boost_VERSION} / 100000") -     math(EXPR _boost_min "${Boost_VERSION} / 100 % 1000") -     if(${_boost_maj}.${_boost_min} VERSION_LESS 1.35) +     if(Boost_VERSION LESS 103500)         list(REMOVE_ITEM Boost_FIND_COMPONENTS system)       endif()    endif() -  FOREACH(COMPONENT ${Boost_FIND_COMPONENTS}) -    STRING(TOUPPER ${COMPONENT} COMPONENT) -    IF(NOT Boost_${COMPONENT}_FOUND) -      SET( _boost_IN_CACHE FALSE) -    ENDIF(NOT Boost_${COMPONENT}_FOUND) -  ENDFOREACH(COMPONENT) -ELSE(Boost_INCLUDE_DIR) -  SET( _boost_IN_CACHE FALSE) -ENDIF(Boost_INCLUDE_DIR) - -IF (_boost_IN_CACHE) +  foreach(COMPONENT ${Boost_FIND_COMPONENTS}) +    string(TOUPPER ${COMPONENT} COMPONENT) +    if(NOT Boost_${COMPONENT}_FOUND) +      set( _boost_IN_CACHE FALSE) +    endif(NOT Boost_${COMPONENT}_FOUND) +  endforeach(COMPONENT) +else(Boost_INCLUDE_DIR) +  set( _boost_IN_CACHE FALSE) +endif(Boost_INCLUDE_DIR) + +if(_boost_IN_CACHE)    # in cache already -  SET(Boost_FOUND TRUE) -  FOREACH(COMPONENT ${Boost_FIND_COMPONENTS}) -    STRING(TOUPPER ${COMPONENT} COMPONENT) +  set(Boost_FOUND TRUE) +  foreach(COMPONENT ${Boost_FIND_COMPONENTS}) +    string(TOUPPER ${COMPONENT} COMPONENT)      _Boost_ADJUST_LIB_VARS( ${COMPONENT} ) -    SET(Boost_LIBRARIES ${Boost_LIBRARIES} ${Boost_${COMPONENT}_LIBRARY}) -  ENDFOREACH(COMPONENT) -  SET(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -  IF(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") -    MATH(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") -    MATH(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") -    MATH(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") -  ENDIF(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") +    set(Boost_LIBRARIES ${Boost_LIBRARIES} ${Boost_${COMPONENT}_LIBRARY}) +  endforeach(COMPONENT) +  set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) +  if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") +    math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") +    math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") +    math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") +  endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")    if(Boost_DEBUG)        message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "                       "boost ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION} " -                     "is already in the cache.  For debugging messages, please clear the cache.") +                     "is already in the cache.  To view debugging messages, please clear the cache.")    endif() -ELSE (_boost_IN_CACHE) +else(_boost_IN_CACHE)    # Need to search for boost    if(Boost_DEBUG)      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " @@ -379,9 +531,15 @@ ELSE (_boost_IN_CACHE)                     "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}")      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "                     "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") +    message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " +                   "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") +    message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " +                   "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") +    message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " +                   "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}")    endif() -  IF(WIN32) +  if(WIN32)      # In windows, automatic linking is performed, so you do not have      # to specify the libraries.  If you are linking to a dynamic      # runtime, then you can choose to link to either a static or a @@ -390,20 +548,20 @@ ELSE (_boost_IN_CACHE)      # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be      # linked dynamically.  Alternatively you can force all Boost      # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. -   +      # This feature can be disabled for Boost library "whatever" by      # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining      # BOOST_ALL_NO_LIB. -   +      # If you want to observe which libraries are being linked against      # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking      # code to emit a #pragma message each time a library is selected      # for linking. -    SET(Boost_LIB_DIAGNOSTIC_DEFINITIONS  +    set(Boost_LIB_DIAGNOSTIC_DEFINITIONS        "-DBOOST_LIB_DIAGNOSTIC" CACHE STRING "Boost diagnostic define") -  ENDIF(WIN32) +  endif(WIN32) -  SET(_boost_INCLUDE_SEARCH_DIRS +  set(_boost_INCLUDE_SEARCH_DIRS_SYSTEM      C:/boost/include      C:/boost      "$ENV{ProgramFiles}/boost/include" @@ -411,29 +569,38 @@ ELSE (_boost_IN_CACHE)      /sw/local/include    ) +  _Boost_CHECK_SPELLING(Boost_ROOT) +  _Boost_CHECK_SPELLING(Boost_LIBRARYDIR) +  _Boost_CHECK_SPELLING(Boost_INCLUDEDIR) + +  # If BOOST_ROOT was defined in the environment, use it. +  if (NOT BOOST_ROOT AND NOT $ENV{Boost_DIR} STREQUAL "") +    set(BOOST_ROOT $ENV{Boost_DIR}) +  endif() +    # If BOOST_ROOT was defined in the environment, use it.    if (NOT BOOST_ROOT AND NOT $ENV{BOOST_ROOT} STREQUAL "")      set(BOOST_ROOT $ENV{BOOST_ROOT}) -  endif(NOT BOOST_ROOT AND NOT $ENV{BOOST_ROOT} STREQUAL "") +  endif()    # If BOOSTROOT was defined in the environment, use it.    if (NOT BOOST_ROOT AND NOT $ENV{BOOSTROOT} STREQUAL "")      set(BOOST_ROOT $ENV{BOOSTROOT}) -  endif(NOT BOOST_ROOT AND NOT $ENV{BOOSTROOT} STREQUAL "") +  endif()    # If BOOST_INCLUDEDIR was defined in the environment, use it. -  IF( NOT $ENV{BOOST_INCLUDEDIR} STREQUAL "" ) +  if( NOT $ENV{BOOST_INCLUDEDIR} STREQUAL "" )      set(BOOST_INCLUDEDIR $ENV{BOOST_INCLUDEDIR}) -  ENDIF( NOT $ENV{BOOST_INCLUDEDIR} STREQUAL "" ) -   +  endif() +    # If BOOST_LIBRARYDIR was defined in the environment, use it. -  IF( NOT $ENV{BOOST_LIBRARYDIR} STREQUAL "" ) +  if( NOT $ENV{BOOST_LIBRARYDIR} STREQUAL "" )      set(BOOST_LIBRARYDIR $ENV{BOOST_LIBRARYDIR}) -  ENDIF( NOT $ENV{BOOST_LIBRARYDIR} STREQUAL "" ) -   -  IF( BOOST_ROOT ) +  endif() + +  if( BOOST_ROOT )      file(TO_CMAKE_PATH ${BOOST_ROOT} BOOST_ROOT) -  ENDIF( BOOST_ROOT ) +  endif()    if(Boost_DEBUG)      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " @@ -448,50 +615,54 @@ ELSE (_boost_IN_CACHE)                     "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}")    endif() -  IF( BOOST_ROOT ) -    SET(_boost_INCLUDE_SEARCH_DIRS  -      ${BOOST_ROOT}/include  +  if( Boost_NO_SYSTEM_PATHS) +    set(_boost_FIND_OPTIONS NO_CMAKE_SYSTEM_PATH) +  else() +    set(_boost_INCLUDE_SEARCH_DIRS ${_boost_INCLUDE_SEARCH_DIRS_SYSTEM}) +  endif() + +  if( BOOST_ROOT ) +    set(_boost_INCLUDE_SEARCH_DIRS +      ${BOOST_ROOT}/include        ${BOOST_ROOT}        ${_boost_INCLUDE_SEARCH_DIRS}) -  ENDIF( BOOST_ROOT ) +  endif() -  IF( BOOST_INCLUDEDIR ) +  # prepend BOOST_INCLUDEDIR to search path if specified +  if( BOOST_INCLUDEDIR )      file(TO_CMAKE_PATH ${BOOST_INCLUDEDIR} BOOST_INCLUDEDIR) -    SET(_boost_INCLUDE_SEARCH_DIRS  +    set(_boost_INCLUDE_SEARCH_DIRS        ${BOOST_INCLUDEDIR} ${_boost_INCLUDE_SEARCH_DIRS}) -  ENDIF( BOOST_INCLUDEDIR ) +  endif( BOOST_INCLUDEDIR )    # ------------------------------------------------------------------------ -  #  Search for Boost include DIR  +  #  Search for Boost include DIR    # ------------------------------------------------------------------------    # Try to find Boost by stepping backwards through the Boost versions    # we know about. -  IF( NOT Boost_INCLUDE_DIR ) +  if( NOT Boost_INCLUDE_DIR )      # Build a list of path suffixes for each version. -    SET(_boost_PATH_SUFFIXES) -    FOREACH(_boost_VER ${_boost_TEST_VERSIONS}) +    set(_boost_PATH_SUFFIXES) +    foreach(_boost_VER ${_boost_TEST_VERSIONS})        # Add in a path suffix, based on the required version, ideally        # we could read this from version.hpp, but for that to work we'd        # need to know the include dir already        set(_boost_BOOSTIFIED_VERSION)        # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 -      IF(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+") -          STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3"  +      if(_boost_VER MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+") +          string(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1_\\2_\\3"              _boost_BOOSTIFIED_VERSION ${_boost_VER}) -      ELSEIF(_boost_VER MATCHES "[0-9]+\\.[0-9]+") -          STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2"  +      elseif(_boost_VER MATCHES "[0-9]+\\.[0-9]+") +          string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1_\\2"              _boost_BOOSTIFIED_VERSION ${_boost_VER}) -      ENDIF() -       -      list(APPEND _boost_PATH_SUFFIXES "boost-${_boost_BOOSTIFIED_VERSION}") -      if(WIN32) -        # For BoostPro's underscores (and others?) -        list(APPEND _boost_PATH_SUFFIXES "boost_${_boost_BOOSTIFIED_VERSION}")        endif() -    ENDFOREACH(_boost_VER) -       +      list(APPEND _boost_PATH_SUFFIXES "boost-${_boost_BOOSTIFIED_VERSION}") +      list(APPEND _boost_PATH_SUFFIXES "boost_${_boost_BOOSTIFIED_VERSION}") + +    endforeach(_boost_VER) +      if(Boost_DEBUG)        message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "                       "Include debugging info:") @@ -502,61 +673,62 @@ ELSE (_boost_IN_CACHE)      endif()      # Look for a standard boost header file. -    FIND_PATH(Boost_INCLUDE_DIR +    find_path(Boost_INCLUDE_DIR        NAMES         boost/config.hpp        HINTS         ${_boost_INCLUDE_SEARCH_DIRS}        PATH_SUFFIXES ${_boost_PATH_SUFFIXES} +      ${_boost_FIND_OPTIONS}        ) -  ENDIF( NOT Boost_INCLUDE_DIR ) -   +  endif( NOT Boost_INCLUDE_DIR ) +    # ------------------------------------------------------------------------    #  Extract version information from version.hpp    # ------------------------------------------------------------------------ -  IF(Boost_INCLUDE_DIR) +  if(Boost_INCLUDE_DIR)      # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp      # Read the whole file:      # -    SET(BOOST_VERSION 0) -    SET(BOOST_LIB_VERSION "") -    FILE(READ "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS) +    set(BOOST_VERSION 0) +    set(BOOST_LIB_VERSION "") +    file(READ "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS)      if(Boost_DEBUG)        message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "                       "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp")      endif() -   -    STRING(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1" Boost_VERSION "${_boost_VERSION_HPP_CONTENTS}") -    STRING(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" Boost_LIB_VERSION "${_boost_VERSION_HPP_CONTENTS}") -   -    SET(Boost_LIB_VERSION ${Boost_LIB_VERSION} CACHE INTERNAL "The library version string for boost libraries") -    SET(Boost_VERSION ${Boost_VERSION} CACHE INTERNAL "The version number for boost libraries") -     -    IF(NOT "${Boost_VERSION}" STREQUAL "0") -      MATH(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") -      MATH(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") -      MATH(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") + +    string(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1" Boost_VERSION "${_boost_VERSION_HPP_CONTENTS}") +    string(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" Boost_LIB_VERSION "${_boost_VERSION_HPP_CONTENTS}") + +    set(Boost_LIB_VERSION ${Boost_LIB_VERSION} CACHE INTERNAL "The library version string for boost libraries") +    set(Boost_VERSION ${Boost_VERSION} CACHE INTERNAL "The version number for boost libraries") + +    if(NOT "${Boost_VERSION}" STREQUAL "0") +      math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") +      math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") +      math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100")        set(Boost_ERROR_REASON            "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") -    ENDIF(NOT "${Boost_VERSION}" STREQUAL "0") +    endif(NOT "${Boost_VERSION}" STREQUAL "0")      if(Boost_DEBUG)        message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "                       "version.hpp reveals boost "                       "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")      endif() -  ELSE(Boost_INCLUDE_DIR) +  else(Boost_INCLUDE_DIR)      set(Boost_ERROR_REASON        "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -  ENDIF(Boost_INCLUDE_DIR) -   +  endif(Boost_INCLUDE_DIR) +    # ------------------------------------------------------------------------    #  Suffix initialization and compiler suffix detection.    # ------------------------------------------------------------------------    # Setting some more suffixes for the library -  SET (Boost_LIB_PREFIX "") -  if ( WIN32 AND Boost_USE_STATIC_LIBS ) -    SET (Boost_LIB_PREFIX "lib") +  set(Boost_LIB_PREFIX "") +  if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) +    set(Boost_LIB_PREFIX "lib")    endif()    if (Boost_COMPILER) @@ -571,62 +743,64 @@ ELSE (_boost_IN_CACHE)      # please report them and use the Boost_COMPILER variable      # to work around the problems.      if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" -        OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"  +        OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"          OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc")        if(WIN32)          set (_boost_COMPILER "-iw")        else()          set (_boost_COMPILER "-il")        endif() -    elseif (MSVC90) -      SET (_boost_COMPILER "-vc90") +    elseif (MSVC11) +      set(_boost_COMPILER "-vc110")      elseif (MSVC10) -      SET (_boost_COMPILER "-vc100") +      set(_boost_COMPILER "-vc100") +    elseif (MSVC90) +      set(_boost_COMPILER "-vc90")      elseif (MSVC80) -      SET (_boost_COMPILER "-vc80") +      set(_boost_COMPILER "-vc80")      elseif (MSVC71) -      SET (_boost_COMPILER "-vc71") +      set(_boost_COMPILER "-vc71")      elseif (MSVC70) # Good luck! -      SET (_boost_COMPILER "-vc7") # yes, this is correct +      set(_boost_COMPILER "-vc7") # yes, this is correct      elseif (MSVC60) # Good luck! -      SET (_boost_COMPILER "-vc6") # yes, this is correct +      set(_boost_COMPILER "-vc6") # yes, this is correct      elseif (BORLAND) -      SET (_boost_COMPILER "-bcb") +      set(_boost_COMPILER "-bcb")      elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "SunPro")        set(_boost_COMPILER "-sw")      elseif (MINGW)        if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) -          SET(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 +          set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34        else()          _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) -        SET (_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") +        set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}")        endif()      elseif (UNIX)        if (CMAKE_COMPILER_IS_GNUCXX)          if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) -          SET(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 +          set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34          else()            _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION)            # Determine which version of GCC we have. -          IF(APPLE) -            IF(Boost_MINOR_VERSION) -              IF(${Boost_MINOR_VERSION} GREATER 35) +          if(APPLE) +            if(Boost_MINOR_VERSION) +              if(${Boost_MINOR_VERSION} GREATER 35)                  # In Boost 1.36.0 and newer, the mangled compiler name used                  # on Mac OS X/Darwin is "xgcc". -                SET(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") -              ELSE(${Boost_MINOR_VERSION} GREATER 35) +                set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") +              else(${Boost_MINOR_VERSION} GREATER 35)                  # In Boost <= 1.35.0, there is no mangled compiler name for                  # the Mac OS X/Darwin version of GCC. -                SET(_boost_COMPILER "") -              ENDIF(${Boost_MINOR_VERSION} GREATER 35) -            ELSE(Boost_MINOR_VERSION) +                set(_boost_COMPILER "") +              endif(${Boost_MINOR_VERSION} GREATER 35) +            else(Boost_MINOR_VERSION)                # We don't know the Boost version, so assume it's                # pre-1.36.0. -              SET(_boost_COMPILER "") -            ENDIF(Boost_MINOR_VERSION) -          ELSE() -            SET (_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") -          ENDIF() +              set(_boost_COMPILER "") +            endif(Boost_MINOR_VERSION) +          else() +            set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") +          endif()          endif()        endif (CMAKE_COMPILER_IS_GNUCXX)      endif() @@ -636,7 +810,7 @@ ELSE (_boost_IN_CACHE)      endif()    endif(Boost_COMPILER) -  SET (_boost_MULTITHREADED "-mt") +  set (_boost_MULTITHREADED "-mt")    if( NOT Boost_USE_MULTITHREADED )      set (_boost_MULTITHREADED "")    endif() @@ -645,32 +819,67 @@ ELSE (_boost_IN_CACHE)        "_boost_MULTITHREADED = ${_boost_MULTITHREADED}")    endif() -  SET( _boost_STATIC_TAG "") -  set( _boost_ABI_TAG "") -  IF (WIN32) -    IF(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" +  #====================== +  # Systematically build up the Boost ABI tag +  # http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming +  set( _boost_RELEASE_ABI_TAG "-") +  set( _boost_DEBUG_ABI_TAG   "-") +  # Key       Use this library when: +  #  s        linking statically to the C++ standard library and +  #           compiler runtime support libraries. +  if(Boost_USE_STATIC_RUNTIME) +    set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") +    set( _boost_DEBUG_ABI_TAG   "${_boost_DEBUG_ABI_TAG}s") +  endif() +  #  g        using debug versions of the standard and runtime +  #           support libraries +  if(WIN32) +    if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"              OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") -      SET (_boost_ABI_TAG "g") -    ENDIF() -    IF( Boost_USE_STATIC_LIBS ) -      SET( _boost_STATIC_TAG "-s") -    ENDIF( Boost_USE_STATIC_LIBS ) -  ENDIF(WIN32) -  SET (_boost_ABI_TAG "${_boost_ABI_TAG}d") +      set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") +    endif() +  endif() +  #  y        using special debug build of python +  if(Boost_USE_DEBUG_PYTHON) +    set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") +  endif() +  #  d        using a debug version of your code +  set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") +  #  p        using the STLport standard library rather than the +  #           default one supplied with your compiler +  if(Boost_USE_STLPORT) +    set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") +    set( _boost_DEBUG_ABI_TAG   "${_boost_DEBUG_ABI_TAG}p") +  endif() +  #  n        using the STLport deprecated "native iostreams" feature +  if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) +    set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") +    set( _boost_DEBUG_ABI_TAG   "${_boost_DEBUG_ABI_TAG}n") +  endif() +    if(Boost_DEBUG)      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " -      "_boost_STATIC_TAG = ${_boost_STATIC_TAG}") +      "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}")      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " -      "_boost_ABI_TAG = ${_boost_ABI_TAG}") +      "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}")    endif()    # ------------------------------------------------------------------------    #  Begin finding boost libraries    # ------------------------------------------------------------------------ -  SET(_boost_LIBRARIES_SEARCH_DIRS +  if(BOOST_ROOT) +    set(_boost_LIBRARY_SEARCH_DIRS_ALWAYS +      ${BOOST_ROOT}/lib +      ${BOOST_ROOT}/stage/lib) +  endif() +  set(_boost_LIBRARY_SEARCH_DIRS_ALWAYS +    ${_boost_LIBRARY_SEARCH_DIRS_ALWAYS}      ${Boost_INCLUDE_DIR}/lib      ${Boost_INCLUDE_DIR}/../lib +    ${Boost_INCLUDE_DIR}/stage/lib +  ) +  set(_boost_LIBRARY_SEARCH_DIRS_SYSTEM      C:/boost/lib      C:/boost      "$ENV{ProgramFiles}/boost/boost_${Boost_MAJOR_VERSION}_${Boost_MINOR_VERSION}_${Boost_SUBMINOR_VERSION}/lib" @@ -679,78 +888,158 @@ ELSE (_boost_IN_CACHE)      "$ENV{ProgramFiles}/boost"      /sw/local/lib    ) -  IF( BOOST_ROOT ) -    SET(_boost_LIBRARIES_SEARCH_DIRS  -      ${BOOST_ROOT}/lib  -      ${BOOST_ROOT}/stage/lib  -      ${_boost_LIBRARIES_SEARCH_DIRS}) -  ENDIF( BOOST_ROOT ) - -  IF( BOOST_LIBRARYDIR ) +  set(_boost_LIBRARY_SEARCH_DIRS ${_boost_LIBRARY_SEARCH_DIRS_ALWAYS}) +  if( Boost_NO_SYSTEM_PATHS ) +    set(_boost_FIND_OPTIONS NO_CMAKE_SYSTEM_PATH) +  else() +    list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_boost_LIBRARY_SEARCH_DIRS_SYSTEM}) +  endif() + +  # prepend BOOST_LIBRARYDIR to search path if specified +  if( BOOST_LIBRARYDIR )      file(TO_CMAKE_PATH ${BOOST_LIBRARYDIR} BOOST_LIBRARYDIR) -    SET(_boost_LIBRARIES_SEARCH_DIRS  -      ${BOOST_LIBRARYDIR} ${_boost_LIBRARIES_SEARCH_DIRS}) -  ENDIF( BOOST_LIBRARYDIR ) +    set(_boost_LIBRARY_SEARCH_DIRS +      ${BOOST_LIBRARYDIR} ${_boost_LIBRARY_SEARCH_DIRS}) +  endif()    if(Boost_DEBUG)      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " -      "_boost_LIBRARIES_SEARCH_DIRS = ${_boost_LIBRARIES_SEARCH_DIRS}") -  endif() - -  FOREACH(COMPONENT ${Boost_FIND_COMPONENTS}) -    STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) -    SET( Boost_${UPPERCOMPONENT}_LIBRARY "Boost_${UPPERCOMPONENT}_LIBRARY-NOTFOUND" ) -    SET( Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE-NOTFOUND" ) -    SET( Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG-NOTFOUND") - -    # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -    IF( Boost_USE_STATIC_LIBS ) -      SET( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) -      IF(WIN32) -        SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) -      ELSE(WIN32) -        SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) -      ENDIF(WIN32) -    ENDIF( Boost_USE_STATIC_LIBS ) - -    FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE -        NAMES  ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_STATIC_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_STATIC_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_STATIC_TAG} -        HINTS  ${_boost_LIBRARIES_SEARCH_DIRS} +      "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") +  endif() + +  # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES +  if( Boost_USE_STATIC_LIBS ) +    set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) +    if(WIN32) +      set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) +    else() +      set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) +    endif() +  endif() + +  # We want to use the tag inline below without risking double dashes +  if(_boost_RELEASE_ABI_TAG) +    if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") +      set(_boost_RELEASE_ABI_TAG "") +    endif() +  endif() +  if(_boost_DEBUG_ABI_TAG) +    if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") +      set(_boost_DEBUG_ABI_TAG "") +    endif() +  endif() + +  # The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled +  # on WIN32 was to: +  #  1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) +  #  2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) +  # We maintain this behavior since changing it could break people's builds. +  # To disable the ambiguous behavior, the user need only +  # set Boost_USE_STATIC_RUNTIME either ON or OFF. +  set(_boost_STATIC_RUNTIME_WORKAROUND false) +  if(WIN32 AND Boost_USE_STATIC_LIBS) +    if(NOT DEFINED Boost_USE_STATIC_RUNTIME) +      set(_boost_STATIC_RUNTIME_WORKAROUND true) +    endif() +  endif() + + +  foreach(COMPONENT ${Boost_FIND_COMPONENTS}) +    string(TOUPPER ${COMPONENT} UPPERCOMPONENT) +    set( Boost_${UPPERCOMPONENT}_LIBRARY "Boost_${UPPERCOMPONENT}_LIBRARY-NOTFOUND" ) +    set( Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE-NOTFOUND" ) +    set( Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG-NOTFOUND") + +    set( _boost_docstring_release "Boost ${COMPONENT} library (release)") +    set( _boost_docstring_debug   "Boost ${COMPONENT} library (debug)") + +    # +    # Find RELEASE libraries +    # +    set(_boost_RELEASE_NAMES +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} +      ${Boost_LIB_PREFIX}boost_${COMPONENT} ) +    if(_boost_STATIC_RUNTIME_WORKAROUND) +      set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") +      list(APPEND _boost_RELEASE_NAMES +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) +    endif() +    if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") +       _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) +    endif() +    if(Boost_DEBUG) +      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " +                     "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") +    endif() +    find_library(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE +        NAMES ${_boost_RELEASE_NAMES} +        HINTS ${_boost_LIBRARY_SEARCH_DIRS} +        ${_boost_FIND_OPTIONS} +        DOC "${_boost_docstring_release}"      ) -    FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG -        NAMES  ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}-${_boost_ABI_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_STATIC_TAG}${_boost_ABI_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}-${_boost_ABI_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_STATIC_TAG}${_boost_ABI_TAG}-${Boost_LIB_VERSION} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}-${_boost_ABI_TAG} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_STATIC_TAG}${_boost_ABI_TAG} -               ${Boost_LIB_PREFIX}boost_${COMPONENT}-${_boost_ABI_TAG} -        HINTS  ${_boost_LIBRARIES_SEARCH_DIRS} +    # +    # Find DEBUG libraries +    # +    set(_boost_DEBUG_NAMES +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} +      ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED} +      ${Boost_LIB_PREFIX}boost_${COMPONENT} ) +    if(_boost_STATIC_RUNTIME_WORKAROUND) +      set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") +      list(APPEND _boost_DEBUG_NAMES +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} +        ${Boost_LIB_PREFIX}boost_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) +    endif() +    if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") +       _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) +    endif() +    if(Boost_DEBUG) +      message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " +                     "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") +    endif() +    find_library(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG +        NAMES ${_boost_DEBUG_NAMES} +        HINTS ${_boost_LIBRARY_SEARCH_DIRS} +        ${_boost_FIND_OPTIONS} +        DOC "${_boost_docstring_debug}"      ) +    if(Boost_REALPATH) +      _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") +      _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG   "${_boost_docstring_debug}"  ) +    endif() +      _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) -    IF( Boost_USE_STATIC_LIBS ) -      SET(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -    ENDIF( Boost_USE_STATIC_LIBS ) -  ENDFOREACH(COMPONENT) + +  endforeach(COMPONENT) + +  # Restore the original find library ordering +  if( Boost_USE_STATIC_LIBS ) +    set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +  endif()    # ------------------------------------------------------------------------    #  End finding boost libraries    # ------------------------------------------------------------------------ -  SET(Boost_INCLUDE_DIRS +  set(Boost_INCLUDE_DIRS      ${Boost_INCLUDE_DIR}    ) -  SET(Boost_FOUND FALSE) -  IF(Boost_INCLUDE_DIR) -    SET( Boost_FOUND TRUE ) +  set(Boost_FOUND FALSE) +  if(Boost_INCLUDE_DIR) +    set( Boost_FOUND TRUE )      # Check the version of Boost against the requested version.      if (Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) @@ -785,7 +1074,7 @@ ELSE (_boost_IN_CACHE)        if (NOT Boost_FIND_VERSION_PATCH)          set(Boost_FIND_VERSION_PATCH 0)        endif (NOT Boost_FIND_VERSION_PATCH) -       +        # We'll set Boost_FOUND true again if we have an exact version match.        set(Boost_FOUND FALSE)        _Boost_MARK_COMPONENTS_FOUND(OFF) @@ -804,7 +1093,7 @@ ELSE (_boost_IN_CACHE)        set(Boost_ERROR_REASON          "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}")        if (Boost_FIND_VERSION_PATCH) -        set(Boost_ERROR_REASON  +        set(Boost_ERROR_REASON            "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}")        endif (Boost_FIND_VERSION_PATCH)        if (NOT Boost_FIND_VERSION_EXACT) @@ -823,7 +1112,7 @@ ELSE (_boost_IN_CACHE)          string(TOLOWER ${COMPONENT} COMPONENT)          list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT})          set( Boost_FOUND FALSE) -      endif(NOT Boost_${COMPONENT}_FOUND) +      endif()      endforeach(COMPONENT)      if(Boost_DEBUG) @@ -844,67 +1133,67 @@ ELSE (_boost_IN_CACHE)        list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS)        if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS})          set(Boost_ERROR_REASON -          "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set Boost_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") +          "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.")        else (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS})          set(Boost_ERROR_REASON -          "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set Boost_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") +          "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.")        endif (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS})      endif (_Boost_MISSING_COMPONENTS) -    IF( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) +    if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT )        # Compatibility Code for backwards compatibility with CMake        # 2.4's FindBoost module.        # Look for the boost library path.        # Note that the user may not have installed any libraries        # so it is quite possible the Boost_LIBRARY_PATH may not exist. -      SET(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) -     -      IF("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") -        GET_FILENAME_COMPONENT(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) -      ENDIF ("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") -     -      IF("${_boost_LIB_DIR}" MATCHES "/include$") +      set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) + +      if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") +        get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) +      endif() + +      if("${_boost_LIB_DIR}" MATCHES "/include$")          # Strip off the trailing "/include" in the path. -        GET_FILENAME_COMPONENT(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) -      ENDIF("${_boost_LIB_DIR}" MATCHES "/include$") -     -      IF(EXISTS "${_boost_LIB_DIR}/lib") -        SET (_boost_LIB_DIR ${_boost_LIB_DIR}/lib) -      ELSE(EXISTS "${_boost_LIB_DIR}/lib") -        IF(EXISTS "${_boost_LIB_DIR}/stage/lib") -          SET(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) -        ELSE(EXISTS "${_boost_LIB_DIR}/stage/lib") -          SET(_boost_LIB_DIR "") -        ENDIF(EXISTS "${_boost_LIB_DIR}/stage/lib") -      ENDIF(EXISTS "${_boost_LIB_DIR}/lib") -     -      IF(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") -        SET(Boost_LIBRARY_DIRS ${_boost_LIB_DIR} CACHE FILEPATH "Boost library directory") -      ENDIF(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - -    ENDIF( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - -  ELSE(Boost_INCLUDE_DIR) -    SET( Boost_FOUND FALSE) -  ENDIF(Boost_INCLUDE_DIR) - -  IF (Boost_FOUND) -      IF (NOT Boost_FIND_QUIETLY) -        MESSAGE(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") +        get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) +      endif() + +      if(EXISTS "${_boost_LIB_DIR}/lib") +        set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) +      else() +        if(EXISTS "${_boost_LIB_DIR}/stage/lib") +          set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) +        else() +          set(_boost_LIB_DIR "") +        endif() +      endif() + +      if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") +        set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR} CACHE FILEPATH "Boost library directory") +      endif() + +    endif( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) + +  else(Boost_INCLUDE_DIR) +    set( Boost_FOUND FALSE) +  endif(Boost_INCLUDE_DIR) + +  if(Boost_FOUND) +      if(NOT Boost_FIND_QUIETLY) +        message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")          if(Boost_FIND_COMPONENTS)            message(STATUS "Found the following Boost libraries:")          endif() -      ENDIF(NOT Boost_FIND_QUIETLY) -      FOREACH ( COMPONENT  ${Boost_FIND_COMPONENTS} ) -        STRING( TOUPPER ${COMPONENT} UPPERCOMPONENT ) -        IF ( Boost_${UPPERCOMPONENT}_FOUND ) -          IF (NOT Boost_FIND_QUIETLY) -            MESSAGE (STATUS "  ${COMPONENT}") -          ENDIF(NOT Boost_FIND_QUIETLY) -          SET(Boost_LIBRARIES ${Boost_LIBRARIES} ${Boost_${UPPERCOMPONENT}_LIBRARY}) -        ENDIF ( Boost_${UPPERCOMPONENT}_FOUND ) -      ENDFOREACH(COMPONENT) +      endif(NOT Boost_FIND_QUIETLY) +      foreach( COMPONENT  ${Boost_FIND_COMPONENTS} ) +        string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) +        if( Boost_${UPPERCOMPONENT}_FOUND ) +          if(NOT Boost_FIND_QUIETLY) +            message (STATUS "  ${COMPONENT}") +          endif(NOT Boost_FIND_QUIETLY) +          set(Boost_LIBRARIES ${Boost_LIBRARIES} ${Boost_${UPPERCOMPONENT}_LIBRARY}) +        endif( Boost_${UPPERCOMPONENT}_FOUND ) +      endforeach(COMPONENT)    else()      if(Boost_FIND_REQUIRED)        message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") @@ -924,9 +1213,8 @@ ELSE (_boost_IN_CACHE)    endif()    # show the Boost_INCLUDE_DIRS AND Boost_LIBRARIES variables only in the advanced view -  MARK_AS_ADVANCED(Boost_INCLUDE_DIR +  mark_as_advanced(Boost_INCLUDE_DIR        Boost_INCLUDE_DIRS        Boost_LIBRARY_DIRS    ) -ENDIF(_boost_IN_CACHE) - +endif(_boost_IN_CACHE) diff --git a/tests/FindGLEW.cmake b/tests/FindGLEW.cmake index 32c2d6e..fa3071f 100644 --- a/tests/FindGLEW.cmake +++ b/tests/FindGLEW.cmake @@ -32,19 +32,22 @@ IF (WIN32)  ELSE (WIN32)          message(STATUS "GLEW_DIR: " ${GLEW_DIR})  	FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h -                PATHS ${GLEW_DIR}/include /usr/include /usr/local/include +                HINTS ${GLEW_DIR}/include  +		PATHS /usr/include /usr/local/include                  NO_DEFAULT_PATH  		DOC "The directory where GL/glew.h resides")  	FIND_LIBRARY( GLEW_LIBRARY  		NAMES GLEW glew -		PATHS ${GLEW_DIR}/lib /usr/lib /usr/local/lib +		HINTS ${GLEW_DIR}/lib  +		PATHS /usr/lib /usr/local/lib                  NO_DEFAULT_PATH  		DOC "The GLEW library")  ENDIF (WIN32)  IF (GLEW_INCLUDE_PATH)  	SET( GLEW_FOUND 1 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise") -        MESSAGE(STATUS "GLEW found in " ${GLEW_INCLUDE_PATH} " " ${GLEW_LIBRARY}) +        MESSAGE(STATUS "GLEW include found in " ${GLEW_INCLUDE_PATH} ) +        MESSAGE(STATUS "GLEW library found in " ${GLEW_LIBRARY} )  ELSE (GLEW_INCLUDE_PATH)  	SET( GLEW_FOUND 0 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise")  ENDIF (GLEW_INCLUDE_PATH) diff --git a/tests/OffscreenContext.h b/tests/OffscreenContext.h index a079c3f..6eebcba 100644 --- a/tests/OffscreenContext.h +++ b/tests/OffscreenContext.h @@ -2,10 +2,12 @@  #define OFFSCREENCONTEXT_H_  #include <iostream>         // for error output +#include <string>  struct OffscreenContext *create_offscreen_context(int w, int h);  void bind_offscreen_context(OffscreenContext *ctx);  bool teardown_offscreen_context(OffscreenContext *ctx);  bool save_framebuffer(OffscreenContext *ctx, const char *filename); +std::string offscreen_context_getinfo(OffscreenContext *ctx);  #endif diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm index 0c44d7d..990d3a4 100644 --- a/tests/OffscreenContext.mm +++ b/tests/OffscreenContext.mm @@ -2,9 +2,11 @@  #include "imageutils.h"  #include "fbo.h"  #include <iostream> +#include <sstream>  #import <AppKit/AppKit.h>   // for NSOpenGL... - +#include <CoreServices/CoreServices.h> +#include <sys/utsname.h>  #define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } } @@ -17,6 +19,29 @@ struct OffscreenContext    fbo_t *fbo;  }; +std::string offscreen_context_getinfo(OffscreenContext *ctx) +{ +  std::stringstream out; + +  struct utsname name; +  uname(&name); + +  SInt32 majorVersion,minorVersion,bugFixVersion; +   +  Gestalt(gestaltSystemVersionMajor, &majorVersion); +  Gestalt(gestaltSystemVersionMinor, &minorVersion); +  Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); + +  const char *arch = "unknown"; +  if (sizeof(int*) == 4) arch = "32-bit"; +  else if (sizeof(int*) == 8) arch = "64-bit"; + +  out << "GL context creator: Cocoa / CGL\n" +      << "PNG generator: Core Foundation\n" +      << "OS info: Mac OS X " << majorVersion << "." << minorVersion << "." << bugFixVersion << " (" << name.machine << " kernel)\n" +      << "Machine: " << arch << "\n"; +  return out.str(); +}  OffscreenContext *create_offscreen_context(int w, int h)  { @@ -84,6 +109,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)  */  bool save_framebuffer(OffscreenContext *ctx, const char *filename)  { +  if (!ctx || !filename) return false;    // Read pixels from OpenGL    int samplesPerPixel = 4; // R, G, B and A    int rowBytes = samplesPerPixel * ctx->width; diff --git a/tests/OffscreenContext.cc b/tests/OffscreenContextGLX.cc index 839eea9..e607593 100644 --- a/tests/OffscreenContext.cc +++ b/tests/OffscreenContextGLX.cc @@ -44,6 +44,11 @@ See Also  #include <GL/gl.h>  #include <GL/glx.h> +#include <assert.h> +#include <sstream> + +#include <sys/utsname.h> // for uname +  using namespace std;  struct OffscreenContext @@ -66,6 +71,42 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)    ctx.fbo = NULL;  } +string get_os_info() +{ +  struct utsname u; +  stringstream out; + +  if (uname(&u) < 0) +    out << "OS info: unknown, uname() error\n"; +  else { +    out << "OS info: " +      << u.sysname << " " +      << u.release << " " +      << u.version << "\n"; +    out << "Machine: " << u.machine; +  } +  return out.str(); +} + +string offscreen_context_getinfo(OffscreenContext *ctx) +{ +  assert(ctx); + +  if (!ctx->xdisplay) +    return string("No GL Context initialized. No information to report\n"); + +  int major, minor; +  glXQueryVersion(ctx->xdisplay, &major, &minor); + +  stringstream out; +  out << "GL context creator: GLX\n" +      << "PNG generator: lodepng\n" +      << "GLX version: " << major << "." << minor << "\n" +      << get_os_info(); + +  return out.str(); +} +  static XErrorHandler original_xlib_handler = (XErrorHandler) NULL;  static bool XCreateWindow_failed = false;  static int XCreateWindow_error(Display *dpy, XErrorEvent *event) @@ -94,11 +135,15 @@ bool create_glx_dummy_window(OffscreenContext &ctx)    */    int attributes[] = { -    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, +    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, //support all 3, for OpenCSG      GLX_RENDER_TYPE,   GLX_RGBA_BIT, -    GLX_RED_SIZE, 1, -    GLX_GREEN_SIZE, 1, -    GLX_BLUE_SIZE, 1, +    GLX_RED_SIZE, 8, +    GLX_GREEN_SIZE, 8, +    GLX_BLUE_SIZE, 8, +    GLX_ALPHA_SIZE, 8, +    GLX_DEPTH_SIZE, 24, // depth-stencil for OpenCSG +    GLX_STENCIL_SIZE, 8, +    GLX_DOUBLEBUFFER, True,      None    }; @@ -123,8 +168,9 @@ bool create_glx_dummy_window(OffscreenContext &ctx)    Window root = DefaultRootWindow( dpy );    XSetWindowAttributes xwin_attr; -  int width = 42; -  int height = 42; +  int width = ctx.width; +  int height = ctx.height; +  xwin_attr.background_pixmap = None;    xwin_attr.background_pixel = 0;    xwin_attr.border_pixel = 0;    xwin_attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); @@ -137,7 +183,6 @@ bool create_glx_dummy_window(OffscreenContext &ctx)    // Window xWin = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0,0,42,42, 0,0,0 ); -    XSync( dpy, false );    if ( XCreateWindow_failed ) {      XFree( visinfo ); @@ -227,7 +272,6 @@ OffscreenContext *create_offscreen_context(int w, int h)      cerr << "Unable to init GLEW: " << glewGetErrorString(err) << endl;      return NULL;    } -  glew_dump();    ctx->fbo = fbo_new();    if (!fbo_init(ctx->fbo, w, h)) { @@ -256,6 +300,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)  */  bool save_framebuffer(OffscreenContext *ctx, const char *filename)  { +  glXSwapBuffers(ctx->xdisplay, ctx->xwindow);    if (!ctx || !filename) return false;    int samplesPerPixel = 4; // R, G, B and A    GLubyte pixels[ctx->width * ctx->height * samplesPerPixel]; @@ -265,7 +310,7 @@ bool save_framebuffer(OffscreenContext *ctx, const char *filename)    int rowBytes = samplesPerPixel * ctx->width;    unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height);    if (!flippedBuffer) { -    std::cerr << "Unable to allocate flipped buffer for corrected image."; +    cerr << "Unable to allocate flipped buffer for corrected image.";      return 1;    }    flip_image(pixels, flippedBuffer, samplesPerPixel, ctx->width, ctx->height); diff --git a/tests/OffscreenContextWGL.cc b/tests/OffscreenContextWGL.cc index 3b966e2..f36671c 100644 --- a/tests/OffscreenContextWGL.cc +++ b/tests/OffscreenContextWGL.cc @@ -22,6 +22,10 @@ For more info:  #include <GL/gl.h> // must be included after glew.h +#include <map> +#include <string> +#include <sstream> +  using namespace std;  struct OffscreenContext @@ -44,6 +48,45 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)    ctx.fbo = NULL;  } +string get_os_info() +{ +  OSVERSIONINFO osvi; + +  ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); +  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); +  GetVersionEx(&osvi); + +  SYSTEM_INFO si; +  GetSystemInfo(&si); +  map<WORD,const char*> archs; +  archs[PROCESSOR_ARCHITECTURE_AMD64] = "amd64"; +  archs[PROCESSOR_ARCHITECTURE_IA64] = "itanium"; +  archs[PROCESSOR_ARCHITECTURE_INTEL] = "x86"; +  archs[PROCESSOR_ARCHITECTURE_UNKNOWN] = "unknown"; + +  stringstream out; +  out << "OS info: " +      << "Microsoft(TM) Windows(TM) " << osvi.dwMajorVersion << " " +      << osvi.dwMinorVersion << " " << osvi.dwBuildNumber << " " +      << osvi.szCSDVersion; +  if (archs.find(si.wProcessorArchitecture) != archs.end())  +    out << " " << archs[si.wProcessorArchitecture]; +  out << "\n"; + +  out << "Machine: " << si.dwProcessorType; + +  return out.str(); +} + +string offscreen_context_getinfo(OffscreenContext *ctx) +{ +  stringstream out; +  out << "GL context creator: WGL\n" +      << "PNG generator: lodepng\n" +      << get_os_info(); +  return out.str(); +} +  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)   {    return DefWindowProc( hwnd, message, wparam, lparam ); @@ -87,11 +130,15 @@ bool create_wgl_dummy_context(OffscreenContext &ctx)    ZeroMemory( &pixformat, sizeof( pixformat ) );    pixformat.nSize = sizeof( pixformat );    pixformat.nVersion = 1; -  pixformat.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; +  pixformat.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;    pixformat.iPixelType = PFD_TYPE_RGBA; -  pixformat.cColorBits = 24; -  pixformat.cDepthBits = 16; -  pixformat.iLayerType = PFD_MAIN_PLANE; +  pixformat.cGreenBits = 8; +  pixformat.cRedBits = 8; +  pixformat.cBlueBits = 8; +  pixformat.cAlphaBits = 8; +  pixformat.cDepthBits = 24; +  pixformat.cStencilBits = 8; +    chosenformat = ChoosePixelFormat( dev_context, &pixformat );    if (chosenformat==0) {      cerr << "MS GDI - ChoosePixelFormat failed\n"; @@ -142,7 +189,7 @@ OffscreenContext *create_offscreen_context(int w, int h)      cerr << "Unable to init GLEW: " << glewGetErrorString(err) << "\n";      return NULL;    } -  glew_dump(); +  //cerr << glew_dump(0);    ctx->fbo = fbo_new();    if (!fbo_init(ctx->fbo, w, h)) { @@ -172,6 +219,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)  */  bool save_framebuffer(OffscreenContext *ctx, const char *filename)  { +  wglSwapLayerBuffers( ctx->dev_context, WGL_SWAP_MAIN_PLANE );    if (!ctx || !filename) return false;    int samplesPerPixel = 4; // R, G, B and A    vector<GLubyte> pixels(ctx->width * ctx->height * samplesPerPixel); diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc index 46951c1..61d5818 100644 --- a/tests/OffscreenView.cc +++ b/tests/OffscreenView.cc @@ -1,11 +1,12 @@  #include <GL/glew.h>  #include "OffscreenView.h" -#include <opencsg.h> +#include "system-gl.h"  #include "renderer.h"  #include <math.h>  #include <stdio.h>  #include <string.h>  #include <cstdlib> +#include <sstream>  #define FAR_FAR_AWAY 100000.0 @@ -17,19 +18,6 @@ OffscreenView::OffscreenView(size_t width, size_t height)  	this->ctx = create_offscreen_context(width, height);  	if ( this->ctx == NULL ) throw -1; -#ifdef DEBUG -	GLint rbits, gbits, bbits, abits, dbits, sbits; -	glGetIntegerv(GL_RED_BITS, &rbits); -	glGetIntegerv(GL_GREEN_BITS, &gbits); -	glGetIntegerv(GL_BLUE_BITS, &bbits); -	glGetIntegerv(GL_ALPHA_BITS, &abits); -	glGetIntegerv(GL_DEPTH_BITS, &dbits); -	glGetIntegerv(GL_STENCIL_BITS, &sbits); - -	fprintf(stderr, "FBO: RGBA(%d%d%d%d), depth(%d), stencil(%d)\n",  -					rbits, gbits, bbits, abits, dbits, sbits); -#endif -  	initializeGL();  	resizeGL(width, height);  } @@ -68,105 +56,13 @@ void OffscreenView::initializeGL()  	glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);  	glEnable(GL_COLOR_MATERIAL); -#ifdef ENABLE_OPENCSG -	const char *openscad_disable_gl20_env = getenv("OPENSCAD_DISABLE_GL20"); -	if (openscad_disable_gl20_env && !strcmp(openscad_disable_gl20_env, "0")) -		openscad_disable_gl20_env = NULL; -	if (glewIsSupported("GL_VERSION_2_0") && openscad_disable_gl20_env == NULL) -	{ -		const char *vs_source = -			"uniform float xscale, yscale;\n" -			"attribute vec3 pos_b, pos_c;\n" -			"attribute vec3 trig, mask;\n" -			"varying vec3 tp, tr;\n" -			"varying float shading;\n" -			"void main() {\n" -			"  vec4 p0 = gl_ModelViewProjectionMatrix * gl_Vertex;\n" -			"  vec4 p1 = gl_ModelViewProjectionMatrix * vec4(pos_b, 1.0);\n" -			"  vec4 p2 = gl_ModelViewProjectionMatrix * vec4(pos_c, 1.0);\n" -			"  float a = distance(vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n" -			"  float b = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w));\n" -			"  float c = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n" -			"  float s = (a + b + c) / 2.0;\n" -			"  float A = sqrt(s*(s-a)*(s-b)*(s-c));\n" -			"  float ha = 2.0*A/a;\n" -			"  gl_Position = p0;\n" -			"  tp = mask * ha;\n" -			"  tr = trig;\n" -			"  vec3 normal, lightDir;\n" -			"  normal = normalize(gl_NormalMatrix * gl_Normal);\n" -			"  lightDir = normalize(vec3(gl_LightSource[0].position));\n" -			"  shading = abs(dot(normal, lightDir));\n" -			"}\n"; - -		const char *fs_source = -			"uniform vec4 color1, color2;\n" -			"varying vec3 tp, tr, tmp;\n" -			"varying float shading;\n" -			"void main() {\n" -			"  gl_FragColor = vec4(color1.r * shading, color1.g * shading, color1.b * shading, color1.a);\n" -			"  if (tp.x < tr.x || tp.y < tr.y || tp.z < tr.z)\n" -			"    gl_FragColor = color2;\n" -			"}\n"; - -		GLuint vs = glCreateShader(GL_VERTEX_SHADER); -		glShaderSource(vs, 1, (const GLchar**)&vs_source, NULL); -		glCompileShader(vs); - -		GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); -		glShaderSource(fs, 1, (const GLchar**)&fs_source, NULL); -		glCompileShader(fs); - -		GLuint edgeshader_prog = glCreateProgram(); -		glAttachShader(edgeshader_prog, vs); -		glAttachShader(edgeshader_prog, fs); -		glLinkProgram(edgeshader_prog); - -		shaderinfo[0] = edgeshader_prog; -		shaderinfo[1] = glGetUniformLocation(edgeshader_prog, "color1"); -		shaderinfo[2] = glGetUniformLocation(edgeshader_prog, "color2"); -		shaderinfo[3] = glGetAttribLocation(edgeshader_prog, "trig"); -		shaderinfo[4] = glGetAttribLocation(edgeshader_prog, "pos_b"); -		shaderinfo[5] = glGetAttribLocation(edgeshader_prog, "pos_c"); -		shaderinfo[6] = glGetAttribLocation(edgeshader_prog, "mask"); -		shaderinfo[7] = glGetUniformLocation(edgeshader_prog, "xscale"); -		shaderinfo[8] = glGetUniformLocation(edgeshader_prog, "yscale"); - -		GLenum err = glGetError(); -		if (err != GL_NO_ERROR) { -			fprintf(stderr, "OpenGL Error: %s\n", gluErrorString(err)); -		} - -		GLint status; -		glGetProgramiv(edgeshader_prog, GL_LINK_STATUS, &status); -		if (status == GL_FALSE) { -			int loglen; -			char logbuffer[1000]; -			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); -			fprintf(stderr, "OpenGL Program Linker Error:\n%.*s", loglen, logbuffer); -		} else { -			int loglen; -			char logbuffer[1000]; -			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); -			if (loglen > 0) { -				fprintf(stderr, "OpenGL Program Link OK:\n%.*s", loglen, logbuffer); -			} -			glValidateProgram(edgeshader_prog); -			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); -			if (loglen > 0) { -				fprintf(stderr, "OpenGL Program Validation results:\n%.*s", loglen, logbuffer); -			} -		} -	} -#endif /* ENABLE_OPENCSG */ +  }  void OffscreenView::resizeGL(int w, int h)  { -#ifdef ENABLE_OPENCSG -	shaderinfo[9] = w; -	shaderinfo[10] = h; -#endif +	this->width = w; +	this->height = h;  	glViewport(0, 0, w, h);  	w_h_ratio = sqrt((double)w / (double)h);  } @@ -237,9 +133,6 @@ void OffscreenView::paintGL()  	glColor3d(1.0, 0.0, 0.0);  	if (this->renderer) { -#ifdef ENABLE_OPENCSG -		OpenCSG::setContext(0); -#endif  		this->renderer->draw(showfaces, showedges);  	}  } @@ -249,6 +142,26 @@ bool OffscreenView::save(const char *filename)  	return save_framebuffer(this->ctx, filename);  } +std::string OffscreenView::getInfo() +{ +	std::stringstream out; +	GLint rbits, gbits, bbits, abits, dbits, sbits; +	glGetIntegerv(GL_RED_BITS, &rbits); +	glGetIntegerv(GL_GREEN_BITS, &gbits); +	glGetIntegerv(GL_BLUE_BITS, &bbits); +	glGetIntegerv(GL_ALPHA_BITS, &abits); +	glGetIntegerv(GL_DEPTH_BITS, &dbits); +	glGetIntegerv(GL_STENCIL_BITS, &sbits); + +	out << glew_dump(false) +	    << "FBO: RGBA(" << rbits << gbits << bbits << abits +	    << "), depth(" << dbits +	    << "), stencil(" << sbits << ")\n" +	    << offscreen_context_getinfo(this->ctx); + +	return out.str(); +} +  void OffscreenView::setCamera(const Eigen::Vector3d &pos, const Eigen::Vector3d ¢er)  {  	this->camera_eye = pos; diff --git a/tests/OffscreenView.h b/tests/OffscreenView.h index e3c8579..8b98b29 100644 --- a/tests/OffscreenView.h +++ b/tests/OffscreenView.h @@ -4,6 +4,7 @@  #include "OffscreenContext.h"  #include <Eigen/Core>  #include <Eigen/Geometry> +#include <string>  #ifndef _MSC_VER  #include <stdint.h>  #endif @@ -22,9 +23,12 @@ public:  	void setupOrtho(bool offset=false);  	void paintGL();  	bool save(const char *filename); +	std::string getInfo();  	GLint shaderinfo[11];  	OffscreenContext *ctx; +	size_t width; +	size_t height;  private:  	Renderer *renderer;  	double w_h_ratio; diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 864d40e..a58c1fd 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -14,6 +14,7 @@  #include "CGALEvaluator.h"  #include "PolySetCGALEvaluator.h" +#include <opencsg.h>  #include "OpenCSGRenderer.h"  #include "ThrownTogetherRenderer.h" @@ -25,8 +26,15 @@  #include <QDir>  #include <QSet>  #include <QTimer> +  #include <sstream> +#include <vector> + +#include <boost/program_options.hpp> +namespace po = boost::program_options; +using std::string; +using std::vector;  using std::cerr;  using std::cout; @@ -64,16 +72,181 @@ AbstractNode *find_root_tag(AbstractNode *n)  	return NULL;  } +string info_dump(OffscreenView *glview) +{ +	assert(glview); + +#ifdef __GNUG__ +#define compiler_info "GCC " << __VERSION__ +#elif defined(_MSC_VER) +#define compiler_info "MSVC " << _MSC_FULL_VER +#else +#define compiler_info "unknown compiler" +#endif + +#ifndef OPENCSG_VERSION_STRING +#define OPENCSG_VERSION_STRING "unknown, <1.3.2" +#endif + +	std::stringstream out; +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +	out << "\nOpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) +            << "\nCompiled by: " << compiler_info +	    << "\nCompile date: " << __DATE__ +	    << "\nBoost version: " << BOOST_LIB_VERSION +	    << "\nEigen version: " << EIGEN_WORLD_VERSION << "." +	    << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION +	    << "\nCGAL version: " << TOSTRING(CGAL_VERSION) +	    << "\nOpenCSG version: " << OPENCSG_VERSION_STRING +	    << "\n" << glview->getInfo() +	    << "\n"; + +	return out.str(); +} + +po::variables_map parse_options(int argc, char *argv[]) +{ +        po::options_description desc("Allowed options"); +        desc.add_options() +                ("help,h", "help message")//; +                ("info,i", "information on GLEW, OpenGL, OpenSCAD, and OS")//; + +//        po::options_description hidden("Hidden options"); +//        hidden.add_options() +                ("input-file", po::value< vector<string> >(), "input file") +                ("output-file", po::value< vector<string> >(), "ouput file"); + +        po::positional_options_description p; +        p.add("input-file", 1).add("output-file", 1); + +        po::options_description all_options; +        all_options.add(desc); // .add(hidden); + +        po::variables_map vm; +        po::store(po::command_line_parser(argc, argv).options(all_options).positional(p).run(), vm); +	po::notify(vm); + +	return vm; +} + +void enable_opencsg_shaders( OffscreenView *glview ) +{ +	bool ignore_gl_version = true; +	const char *openscad_disable_gl20_env = getenv("OPENSCAD_DISABLE_GL20"); +	if (openscad_disable_gl20_env && !strcmp(openscad_disable_gl20_env, "0")) +		openscad_disable_gl20_env = NULL; +	if (glewIsSupported("GL_VERSION_2_0") && openscad_disable_gl20_env == NULL ) +	{ +		const char *vs_source = +			"uniform float xscale, yscale;\n" +			"attribute vec3 pos_b, pos_c;\n" +			"attribute vec3 trig, mask;\n" +			"varying vec3 tp, tr;\n" +			"varying float shading;\n" +			"void main() {\n" +			"  vec4 p0 = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +			"  vec4 p1 = gl_ModelViewProjectionMatrix * vec4(pos_b, 1.0);\n" +			"  vec4 p2 = gl_ModelViewProjectionMatrix * vec4(pos_c, 1.0);\n" +			"  float a = distance(vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n" +			"  float b = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w));\n" +			"  float c = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n" +			"  float s = (a + b + c) / 2.0;\n" +			"  float A = sqrt(s*(s-a)*(s-b)*(s-c));\n" +			"  float ha = 2.0*A/a;\n" +			"  gl_Position = p0;\n" +			"  tp = mask * ha;\n" +			"  tr = trig;\n" +			"  vec3 normal, lightDir;\n" +			"  normal = normalize(gl_NormalMatrix * gl_Normal);\n" +			"  lightDir = normalize(vec3(gl_LightSource[0].position));\n" +			"  shading = abs(dot(normal, lightDir));\n" +			"}\n"; + +		const char *fs_source = +			"uniform vec4 color1, color2;\n" +			"varying vec3 tp, tr, tmp;\n" +			"varying float shading;\n" +			"void main() {\n" +			"  gl_FragColor = vec4(color1.r * shading, color1.g * shading, color1.b * shading, color1.a);\n" +			"  if (tp.x < tr.x || tp.y < tr.y || tp.z < tr.z)\n" +			"    gl_FragColor = color2;\n" +			"}\n"; + +		GLuint vs = glCreateShader(GL_VERTEX_SHADER); +		glShaderSource(vs, 1, (const GLchar**)&vs_source, NULL); +		glCompileShader(vs); + +		GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); +		glShaderSource(fs, 1, (const GLchar**)&fs_source, NULL); +		glCompileShader(fs); + +		GLuint edgeshader_prog = glCreateProgram(); +		glAttachShader(edgeshader_prog, vs); +		glAttachShader(edgeshader_prog, fs); +		glLinkProgram(edgeshader_prog); + +		glview->shaderinfo[0] = edgeshader_prog; +		glview->shaderinfo[1] = glGetUniformLocation(edgeshader_prog, "color1"); +		glview->shaderinfo[2] = glGetUniformLocation(edgeshader_prog, "color2"); +		glview->shaderinfo[3] = glGetAttribLocation(edgeshader_prog, "trig"); +		glview->shaderinfo[4] = glGetAttribLocation(edgeshader_prog, "pos_b"); +		glview->shaderinfo[5] = glGetAttribLocation(edgeshader_prog, "pos_c"); +		glview->shaderinfo[6] = glGetAttribLocation(edgeshader_prog, "mask"); +		glview->shaderinfo[7] = glGetUniformLocation(edgeshader_prog, "xscale"); +		glview->shaderinfo[8] = glGetUniformLocation(edgeshader_prog, "yscale"); + +		GLenum err = glGetError(); +		if (err != GL_NO_ERROR) { +			fprintf(stderr, "OpenGL Error: %s\n", gluErrorString(err)); +		} + +		GLint status; +		glGetProgramiv(edgeshader_prog, GL_LINK_STATUS, &status); +		if (status == GL_FALSE) { +			int loglen; +			char logbuffer[1000]; +			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); +			fprintf(stderr, "OpenGL Program Linker Error:\n%.*s", loglen, logbuffer); +		} else { +			int loglen; +			char logbuffer[1000]; +			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); +			if (loglen > 0) { +				fprintf(stderr, "OpenGL Program Link OK:\n%.*s", loglen, logbuffer); +			} +			glValidateProgram(edgeshader_prog); +			glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer); +			if (loglen > 0) { +				fprintf(stderr, "OpenGL Program Validation results:\n%.*s", loglen, logbuffer); +			} +		} +	} +	glview->shaderinfo[9] = glview->width; +	glview->shaderinfo[10] = glview->height; +} +  int csgtestcore(int argc, char *argv[], test_type_e test_type)  { -	if (argc != 3) { -		fprintf(stderr, "Usage: %s <file.scad> <output.png>\n", argv[0]); +	bool sysinfo_dump = false; +	const char *filename, *outfilename = NULL; +	po::variables_map vm; +	try { +		vm = parse_options(argc, argv); +	} catch ( po::error e ) { +		cerr << "error parsing options\n"; +	} +	if (vm.count("info")) sysinfo_dump = true; +	if (vm.count("input-file")) +		filename = vm["input-file"].as< vector<string> >().begin()->c_str(); +	if (vm.count("output-file")) +		outfilename = vm["output-file"].as< vector<string> >().begin()->c_str(); + +	if ((!filename || !outfilename) && !sysinfo_dump) { +		cerr << "Usage: " << argv[0] << " <file.scad> <output.png>\n";  		exit(1);  	} -	const char *filename = argv[1]; -	const char *outfilename = argv[2]; -  	Builtins::instance()->initialize();  	QApplication app(argc, argv, false); @@ -107,13 +280,18 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)  	AbstractModule *root_module;  	ModuleInstantiation root_inst; -	root_module = parsefile(filename); +	if (sysinfo_dump) +		root_module = parse("sphere();","",false); +	else +		root_module = parsefile(filename); +  	if (!root_module) {  		exit(1);  	}  	QFileInfo fileInfo(filename); -	QDir::setCurrent(fileInfo.absolutePath()); +	if (!sysinfo_dump) +		QDir::setCurrent(fileInfo.absolutePath());  	AbstractNode::resetIndexCounter();  	AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst); @@ -150,7 +328,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)  	csgInfo.root_chain = new CSGChain();  	csgInfo.root_chain->import(csgInfo.root_norm_term); -	fprintf(stderr, "Normalized CSG tree has %d elements\n", csgInfo.root_chain->polysets.size()); +	fprintf(stderr, "Normalized CSG tree has %d elements\n", int(csgInfo.root_chain->polysets.size()));  	if (csgInfo.highlight_terms.size() > 0) {  		cerr << "Compiling highlights (" << csgInfo.highlight_terms.size() << " CSG Trees)...\n"; @@ -188,6 +366,9 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)  		fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i. Exiting.\n", error);  		exit(1);  	} +	enable_opencsg_shaders(csgInfo.glview); + +	if (sysinfo_dump) cout << info_dump(csgInfo.glview);  	BoundingBox bbox = csgInfo.root_chain->getBoundingBox();  	Vector3d center = (bbox.min() + bbox.max()) / 2; @@ -206,8 +387,11 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)  	else  		csgInfo.glview->setRenderer(&opencsgRenderer); -	csgInfo.glview->paintGL(); +	OpenCSG::setContext(0); +	OpenCSG::setOption(OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject); +	csgInfo.glview->paintGL(); +	  	csgInfo.glview->save(outfilename);  	delete root_node; diff --git a/tests/fbo.cc b/tests/fbo.cc index 2a3342d..a6677c1 100644 --- a/tests/fbo.cc +++ b/tests/fbo.cc @@ -93,6 +93,7 @@ bool fbo_ext_init(fbo_t *fbo, size_t width, size_t height)  		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,  																 GL_RENDERBUFFER_EXT, fbo->depthbuf_id);  		if (report_glerror("specifying depth render buffer EXT")) return false; +  		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,  																 GL_RENDERBUFFER_EXT, fbo->depthbuf_id);  		if (report_glerror("specifying stencil render buffer EXT")) return false; @@ -142,7 +143,12 @@ bool fbo_arb_init(fbo_t *fbo, size_t width, size_t height)      return false;    } -  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,  +  //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,  +  // to prevent Mesa's software renderer from crashing, do this in two stages.  +  // ie. instead of using GL_DEPTH_STENCIL_ATTACHMENT, do DEPTH then STENCIL.  +  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, +                               GL_RENDERBUFFER, fbo->depthbuf_id); +  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,                                  GL_RENDERBUFFER, fbo->depthbuf_id);    if (report_glerror("specifying depth stencil render buffer")) return false; @@ -183,24 +189,25 @@ bool fbo_resize(fbo_t *fbo, size_t width, size_t height)      glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->depthbuf_id);  		if (glewIsSupported("GL_EXT_packed_depth_stencil")) {  			glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); -			if (report_glerror("creating depth stencil render buffer")) return false; +			if (report_glerror("creating EXT depth stencil render buffer")) return false;  		}  		else {  			glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); -			if (report_glerror("creating depth render buffer")) return false; +			if (report_glerror("creating EXT depth render buffer")) return false;  		}      glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->renderbuf_id);      glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA8, width, height); -    if (report_glerror("creating color render buffer")) return false; +    if (report_glerror("creating EXT color render buffer")) return false;    } else { +    glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id); +    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); +    if (report_glerror("creating color render buffer")) return false; +      glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthbuf_id);      glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);      if (report_glerror("creating depth stencil render buffer")) return false; -    glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id); -    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); -    if (report_glerror("creating color render buffer")) return false;    }    return true; diff --git a/tests/regression/cgalpngtest/hull2-tests-expected.png b/tests/regression/cgalpngtest/hull2-tests-expected.pngBinary files differ index 256b349..508974f 100644 --- a/tests/regression/cgalpngtest/hull2-tests-expected.png +++ b/tests/regression/cgalpngtest/hull2-tests-expected.png diff --git a/tests/regression/dumptest/hull2-tests-expected.txt b/tests/regression/dumptest/hull2-tests-expected.txt index 87365a6..d060d1d 100644 --- a/tests/regression/dumptest/hull2-tests-expected.txt +++ b/tests/regression/dumptest/hull2-tests-expected.txt @@ -32,4 +32,28 @@  			}  		}  	} +	multmatrix([[1, 0, 0, 30], [0, 1, 0, -25], [0, 0, 1, 0], [0, 0, 0, 1]]) { +		group() { +			hull() { +				group() { +					group() { +						multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { +							circle($fn = 0, $fa = 12, $fs = 1, r = 3); +						} +						multmatrix([[1, 0, 0, 0], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) { +							circle($fn = 0, $fa = 12, $fs = 1, r = 3); +						} +					} +					group() { +						multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { +							circle($fn = 0, $fa = 12, $fs = 1, r = 3); +						} +						multmatrix([[1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) { +							circle($fn = 0, $fa = 12, $fs = 1, r = 3); +						} +					} +				} +			} +		} +	} diff --git a/tests/regression/opencsgtest/color-tests-expected.png b/tests/regression/opencsgtest/color-tests-expected.pngBinary files differ index b2ef8dd..82ba36a 100644 --- a/tests/regression/opencsgtest/color-tests-expected.png +++ b/tests/regression/opencsgtest/color-tests-expected.png diff --git a/tests/regression/opencsgtest/hull2-tests-expected.png b/tests/regression/opencsgtest/hull2-tests-expected.pngBinary files differ index 66ee6b2..46b266b 100644 --- a/tests/regression/opencsgtest/hull2-tests-expected.png +++ b/tests/regression/opencsgtest/hull2-tests-expected.png diff --git a/tests/regression/opencsgtest/sphere-tests-expected.png b/tests/regression/opencsgtest/sphere-tests-expected.pngBinary files differ index 06161f3..d11e3bf 100644 --- a/tests/regression/opencsgtest/sphere-tests-expected.png +++ b/tests/regression/opencsgtest/sphere-tests-expected.png diff --git a/tests/regression/opencsgtest/testcolornames-expected.png b/tests/regression/opencsgtest/testcolornames-expected.pngBinary files differ index 6fc6569..6c1b107 100644 --- a/tests/regression/opencsgtest/testcolornames-expected.png +++ b/tests/regression/opencsgtest/testcolornames-expected.png diff --git a/tests/regression/throwntogethertest/color-tests-expected.png b/tests/regression/throwntogethertest/color-tests-expected.pngBinary files differ index 6b50080..5d4ed89 100644 --- a/tests/regression/throwntogethertest/color-tests-expected.png +++ b/tests/regression/throwntogethertest/color-tests-expected.png diff --git a/tests/regression/throwntogethertest/hull2-tests-expected.png b/tests/regression/throwntogethertest/hull2-tests-expected.pngBinary files differ index 221cbaf..46b266b 100644 --- a/tests/regression/throwntogethertest/hull2-tests-expected.png +++ b/tests/regression/throwntogethertest/hull2-tests-expected.png diff --git a/tests/regression/throwntogethertest/sphere-tests-expected.png b/tests/regression/throwntogethertest/sphere-tests-expected.pngBinary files differ index 4792668..d11e3bf 100644 --- a/tests/regression/throwntogethertest/sphere-tests-expected.png +++ b/tests/regression/throwntogethertest/sphere-tests-expected.png diff --git a/tests/system-gl.cc b/tests/system-gl.cc index bdf3bf9..2e3f3bc 100644 --- a/tests/system-gl.cc +++ b/tests/system-gl.cc @@ -2,35 +2,40 @@  /* OpenGL helper functions */  #include <iostream> +#include <sstream> +#include <string>  #include "system-gl.h"  #include <boost/algorithm/string.hpp>  using namespace std;  using namespace boost; -void glew_dump(bool dumpall) { -#ifdef DEBUG -  cerr << "GLEW version: " << glewGetString(GLEW_VERSION) << endl -       << "Renderer: " << (const char *)glGetString(GL_RENDERER) << endl -       << "Vendor: " << (const char *)glGetString(GL_VENDOR) << endl -       << "OpenGL version: " << (const char *)glGetString(GL_VERSION) << endl; +string glew_dump(bool dumpall) +{ +  stringstream out; +  out << "GLEW version: " << glewGetString(GLEW_VERSION) << endl +       << "GL Renderer: " << (const char *)glGetString(GL_RENDERER) << endl +       << "GL Vendor: " << (const char *)glGetString(GL_VENDOR) << endl +       << "OpenGL Version: " << (const char *)glGetString(GL_VERSION) << endl; +  out << "GL Extensions: " << endl;    if (dumpall) {      string extensions((const char *)glGetString(GL_EXTENSIONS));      replace_all( extensions, " ", "\n " ); -    cerr << "Extensions: " << endl << " " << extensions << endl; +    out << " " << extensions << endl;    } -  cerr << " GL_ARB_framebuffer_object: "  -       << (glewIsSupported("GL_ARB_framebuffer_object") ? "yes" : "no") -       << endl -       << " GL_EXT_framebuffer_object: "  -       << (glewIsSupported("GL_EXT_framebuffer_object") ? "yes" : "no")   -       << endl -       << " GL_EXT_packed_depth_stencil: "  -       << (glewIsSupported("GL_EXT_packed_depth_stencil") ? "yes" : "no")  -       << endl; -#endif +  out << "GL_ARB_framebuffer_object: " +      << (glewIsSupported("GL_ARB_framebuffer_object") ? "yes" : "no") +      << endl +      << "GL_EXT_framebuffer_object: " +      << (glewIsSupported("GL_EXT_framebuffer_object") ? "yes" : "no") +      << endl +      << "GL_EXT_packed_depth_stencil: " +      << (glewIsSupported("GL_EXT_packed_depth_stencil") ? "yes" : "no") +      << endl; + +  return out.str();  };  bool report_glerror(const char * function) diff --git a/tests/system-gl.h b/tests/system-gl.h index b41e32c..4a8ccac 100644 --- a/tests/system-gl.h +++ b/tests/system-gl.h @@ -2,8 +2,9 @@  #define SYSTEMGL_H_  #include <GL/glew.h> +#include <string> -void glew_dump(bool dumpall = false); +std::string glew_dump(bool dumpall=false);  bool report_glerror(const char *task);  #endif diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py index 8b49f78..848a6eb 100755 --- a/tests/test_cmdline_tool.py +++ b/tests/test_cmdline_tool.py @@ -26,6 +26,7 @@ import re  import getopt  import shutil  import platform +import string  def initialize_environment():      if not options.generate: options.generate = bool(os.getenv("TEST_GENERATE")) @@ -35,6 +36,7 @@ def init_expected_filename(testname, cmd):      global expecteddir, expectedfilename      expecteddir = os.path.join(options.regressiondir, os.path.split(cmd)[1])      expectedfilename = os.path.join(expecteddir, testname + "-expected." + options.suffix) +    expectedfilename = os.path.normpath( expectedfilename )  def verify_test(testname, cmd):      global expectedfilename @@ -47,7 +49,7 @@ def verify_test(testname, cmd):  def execute_and_redirect(cmd, params, outfile):      retval = -1      try: -        proc = subprocess.Popen([cmd] + params, stdout=outfile) +        proc = subprocess.Popen([cmd] + params, stdout=outfile, stderr=subprocess.STDOUT)          out = proc.communicate()[0]          retval = proc.wait()      except: @@ -66,32 +68,52 @@ def compare_text(expected, actual):      return get_normalized_text(expected) == get_normalized_text(actual)  def compare_default(resultfilename): +    print >> sys.stderr, 'diff text compare: ' +    print >> sys.stderr, ' expected textfile: ', expectedfilename +    print >> sys.stderr, ' actual textfile: ', resultfilename      if not compare_text(expectedfilename, resultfilename):           execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)          return False      return True  def compare_png(resultfilename): +    compare_method = 'pixel' +    #args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-composite", "-threshold", "10%", "-blur", "2", "-threshold", "30%", "-format", "%[fx:w*h*mean]", "info:"] +    args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-composite", "-threshold", "10%", "-morphology", "Erode", "Square", "-format", "%[fx:w*h*mean]", "info:"] + +    # for systems with older imagemagick that doesnt support '-morphology' +    # http://www.imagemagick.org/Usage/morphology/#alturnative +    if options.comparator == 'old': +      args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-composite", "-threshold", "10%", "-gaussian-blur","3x65535", "-threshold", "99.99%", "-format", "%[fx:w*h*mean]", "info:"] + +    if options.comparator == 'ncc': +      # for systems where imagemagick crashes when using the above comparators +      args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-metric", "NCC", "tmp.png"] +      options.convert_exec = 'compare' +      compare_method = 'NCC' + +    msg = 'ImageMagick image comparison: '  + options.convert_exec + ' '+ ' '.join(args[2:]) +    msg += '\nexpected image: ' + expectedfilename + '\n' +    print >> sys.stderr, msg      if not resultfilename: -        print >> sys.stderr, "Error: OpenSCAD did not generate an image" +        print >> sys.stderr, "Error: OpenSCAD did not generate an image to test"          return False +    print >> sys.stderr, ' actual image: ', resultfilename -#    args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-composite", "-threshold", "10%", "-blur", "2", "-threshold", "30%", "-format", "%[fx:w*h*mean]", "info:"] -    args = [expectedfilename, resultfilename, "-alpha", "Off", "-compose", "difference", "-composite", "-threshold", "10%", "-morphology", "Erode", "Square", "-format", "%[fx:w*h*mean]", "info:"] -    print >> sys.stderr, 'convert ', ' '.join(args) -    (retval, output) = execute_and_redirect("convert", args, subprocess.PIPE) +    (retval, output) = execute_and_redirect(options.convert_exec, args, subprocess.PIPE) +    print "Imagemagick return", retval, "output:", output      if retval == 0: -        pixelerr = int(float(output.strip())) -        if pixelerr < 32: return True -        else: print >> sys.stderr, pixelerr, ' pixel errors' +	if compare_method=='pixel': +            pixelerr = int(float(output.strip())) +            if pixelerr < 32: return True +            else: print >> sys.stderr, pixelerr, ' pixel errors' +	elif compare_method=='NCC': +            thresh = 0.95 +            ncc_err = float(output.strip()) +            if ncc_err > thresh: return True +            else: print >> sys.stderr, ncc_err, ' Images differ: NCC comparison < ', thresh      return False -# Old compare solution, based on yee_compare -#    print >> sys.stderr, 'Yee image compare: ', expectedfilename, ' ', resultfilename -#    if execute_and_redirect("./yee_compare", [expectedfilename, resultfilename, "-downsample", "1", "-threshold", "150"], sys.stderr) != 0: -#        return False -#    return True -  def compare_with_expected(resultfilename):      if not options.generate:          if "compare_" + options.suffix in globals(): return globals()["compare_" + options.suffix](resultfilename) @@ -143,11 +165,12 @@ def usage():      print >> sys.stderr, "  -g, --generate        Generate expected output for the given tests"      print >> sys.stderr, "  -s, --suffix=<suffix> Write -expected and -actual files with the given suffix instead of .txt"      print >> sys.stderr, "  -t, --test=<name>     Specify test name instead of deducting it from the argument" +    print >> sys.stderr, "  -c, --convexec=<name> Path to ImageMagick 'convert' executable"  if __name__ == '__main__':      # Handle command-line arguments      try: -        opts, args = getopt.getopt(sys.argv[1:], "gs:t:", ["generate", "suffix=", "test="]) +        opts, args = getopt.getopt(sys.argv[1:], "gs:c:t:m:", ["generate", "convexec=", "suffix=", "test=", "comparator="])      except getopt.GetoptError, err:          usage()          sys.exit(2) @@ -165,6 +188,10 @@ if __name__ == '__main__':              else: options.suffix = a          elif o in ("-t", "--test"):              options.testname = a +        elif o in ("-c", "--convexec"):  +            options.convert_exec = os.path.normpath( a ) +        elif o in ("-m", "--comparator"): +            options.comparator = a      # <cmdline-tool> and <argument>      if len(args) < 2: diff --git a/tests/test_pretty_print.py b/tests/test_pretty_print.py new file mode 100755 index 0000000..53fcc37 --- /dev/null +++ b/tests/test_pretty_print.py @@ -0,0 +1,503 @@ +#!/usr/bin/python + +#  Copyright (C) 2011 Don Bright <hugh.m.bright@gmail.com>  +# +#  This program is free software; you can redistribute it and/or modify +#  it under the terms of the GNU General Public License as published by +#  the Free Software Foundation; either version 2 of the License, or +#  (at your option) any later version. +# +#  This program is distributed in the hope that it will be useful, +#  but WITHOUT ANY WARRANTY; without even the implied warranty of +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#  GNU General Public License for more details. +# +#  You should have received a copy of the GNU General Public License +#  along with this program; if not, write to the Free Software +#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + +# +# This program 'pretty prints' the ctest output, namely +# files from builddir/Testing/Temporary.  +# html & wiki output are produced in Testing/Temporary/sysid_report +# +# experimental wiki uploading is available by running  +#  +#  python test_pretty_print.py --upload +# + +# Design philosophy +# +# 1. parse the data (images, logs) into easy-to-use data structures +# 2. wikifiy the data  +# 3. save the wikified data to disk + +# todo +# deal better with the situation where Offscreen rendering fails +# do something if tests for GL extensions for OpenCSG fail (test fail, no image production) +# copy all images, sysinfo.txt to bundle for html/upload (images  +#  can be altered  by subsequent runs) +# why is hash differing +# fix windows so that it won't keep asking 'this program crashed' over and over.  +#  (you can set this in the registry to never happen, but itd be better if the program +#   itself was able to disable that temporarily in it's own process) + +import string,sys,re,os,hashlib,subprocess,textwrap,time,platform + +def tryread(filename): +	data = None +	try: +		f = open(filename,'rb') +		data = f.read() +		f.close() +	except: +		print 'couldn\'t open ',filename +	return data + +def trysave(filename,data): +	try: +		if not os.path.isdir(os.path.dirname(filename)): +			#print 'creating',os.path.dirname(filename) +			os.mkdir(os.path.dirname(filename)) +		f=open(filename,'wb') +		f.write(data) +		f.close() +	except: +		print 'problem writing to',filename +		return None +	return True + +def ezsearch(pattern,str): +	x = re.search(pattern,str,re.DOTALL|re.MULTILINE) +	if x and len(x.groups())>0: return x.group(1).strip() +	return '' +	 +def read_gitinfo(): +	# won't work if run from outside of branch.  +	data = subprocess.Popen(['git','remote','-v'],stdout=subprocess.PIPE).stdout.read() +	origin = ezsearch('^origin *?(.*?)\(fetch.*?$',data) +	upstream = ezsearch('^upstream *?(.*?)\(fetch.*?$',data) +	data = subprocess.Popen(['git','branch'],stdout=subprocess.PIPE).stdout.read() +	branch = ezsearch('^\*(.*?)$',data) +	out  = 'Git branch: ' + branch + ' from origin ' + origin + '\n' +	out += 'Git upstream: ' + upstream + '\n' +	return out + +def read_sysinfo(filename): +	data = tryread(filename) +	if not data:  +		sinfo = platform.sys.platform +		sinfo += '\nsystem cannot create offscreen GL framebuffer object' +		sinfo += '\nsystem cannot create images' +		sysid = platform.sys.platform+'_no_images' +		return sinfo, sysid + +	machine = ezsearch('Machine:(.*?)\n',data) +	machine = machine.replace(' ','-').replace('/','-') + +	osinfo = ezsearch('OS info:(.*?)\n',data) +	osplain = osinfo.split(' ')[0].strip().replace('/','-') +	if 'windows' in osinfo.lower(): osplain = 'win' + +	renderer = ezsearch('GL Renderer:(.*?)\n',data) +	tmp = renderer.split(' ') +	tmp = string.join(tmp[0:3],'-') +	tmp = tmp.split('/')[0] +	renderer = tmp + +	data += read_gitinfo() + +	data += 'Image comparison: ImageMagick' + +	data = data.strip() + +	# create 4 letter hash and stick on end of sysid +	nondate_data = re.sub("\n.*?ompile date.*?\n","\n",data).strip() +	hexhash = hashlib.md5() +	hexhash.update(nondate_data) +	hexhash = hexhash.hexdigest()[-4:].upper() +	hash = '' +	for c in hexhash: hash += chr(ord(c)+97-48)  + +	sysid = osplain + '_' + machine + '_' + renderer + '_' + hash +	sysid = sysid.lower() + +	return data, sysid + +class Test: +	def __init__(self,fullname,time,passed,output,type,actualfile,expectedfile,scadfile,log): +		self.fullname,self.time,self.passed,self.output = \ +			fullname, time, passed, output +		self.type, self.actualfile, self.expectedfile, self.scadfile = \ +			type, actualfile, expectedfile, scadfile +		self.fulltestlog = log + +	def __str__(self): +		x = 'fullname: ' + self.fullname +		x+= '\nactualfile: ' + self.actualfile +		x+= '\nexpectedfile: ' + self.expectedfile +		x+= '\ntesttime: ' + self.time +		x+= '\ntesttype: ' + self.type +		x+= '\npassed: ' + str(self.passed) +		x+= '\nscadfile: ' + self.scadfile +		x+= '\noutput bytes: ' + str(len(self.output)) +		x+= '\ntestlog bytes: ' + str(len(self.fulltestlog)) +		x+= '\n' +		return x + +def parsetest(teststring): +	patterns = ["Test:(.*?)\n", # fullname +		"Test time =(.*?) sec\n", +		"Test time.*?Test (Passed)", # pass/fail +		"Output:(.*?)<end of output>", +		'Command:.*?-s" "(.*?)"', # type +		"actual .*?:(.*?)\n", +		"expected .*?:(.*?)\n", +		'Command:.*?(testdata.*?)"' # scadfile  +		] +	hits = map( lambda pattern: ezsearch(pattern,teststring), patterns ) +	test = Test(hits[0],hits[1],hits[2]=='Passed',hits[3],hits[4],hits[5],hits[6],hits[7],teststring) +	test.actualfile_data = tryread(test.actualfile) +	test.expectedfile_data = tryread(test.expectedfile) +	return test + +def parselog(data): +	startdate = ezsearch('Start testing: (.*?)\n',data) +	enddate = ezsearch('End testing: (.*?)\n',data) +	pattern = '([0-9]*/[0-9]* Testing:.*?time elapsed.*?\n)' +	test_chunks = re.findall(pattern,data,re.S) +	tests = map( parsetest, test_chunks ) +	tests = sorted(tests, key = lambda t:t.passed) +	return startdate, tests, enddate + +def load_makefiles(builddir): +	filelist = [] +	for root, dirs, files in os.walk(builddir): +		for fname in files: filelist += [ os.path.join(root, fname) ] +	files  = filter(lambda x: 'build.make' in os.path.basename(x), filelist) +	files += filter(lambda x: 'flags.make' in os.path.basename(x), filelist) +	files = filter(lambda x: 'esting' not in x and 'emporary' not in x, files) +	result = {} +	for fname in files: +		result[fname.replace(builddir,'')] = open(fname,'rb').read() +	return result + +def wikify_filename(fname, wiki_rootpath, sysid): +	wikifname = fname.replace('/','_').replace('\\','_').strip('.') +	return wiki_rootpath + '_' + sysid + '_' + wikifname + +def towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles): + +	wiki_template = """ +<h3>[[WIKI_ROOTPATH]] test run report</h3> + +'''Sysid''': SYSID + +'''Result summary''': NUMPASSED / NUMTESTS tests passed ( PERCENTPASSED % ) <br> + +'''System info''': +<pre> +SYSINFO +</pre> + +start time: STARTDATE <br> +end time  : ENDDATE <br> + +'''Image tests''' + +<REPEAT1> +{| border=1 cellspacing=0 cellpadding=1 +|- +| colspan=2 | FTESTNAME   +|- +| Expected image || Actual image +|- +| [[File:EXPECTEDFILE|250px]] || ACTUALFILE_WIKI +|} + +<pre> +TESTLOG +</pre> + + + +</REPEAT1> + + +'''Text tests''' + +<REPEAT2> +{|border=1 cellspacing=0 cellpadding=1 +|- +| FTESTNAME +|} + +<pre> +TESTLOG +</pre> + + +</REPEAT2> + +'''build.make and flags.make''' +<REPEAT3> +*[[MAKEFILE_NAME]] +</REPEAT3> +""" +	txtpages = {} +	imgs = {} +	passed_tests = filter(lambda x: x.passed, tests) +	failed_tests = filter(lambda x: not x.passed, tests) + +	tests_to_report = tests +	if failed_only: tests_to_report = failed_tests + +	try: percent = str(int(100.0*len(passed_tests) / len(tests))) +	except ZeroDivisionError: percent = 'n/a' +	s = wiki_template +	repeat1 = ezsearch('(<REPEAT1>.*?</REPEAT1>)',s) +	repeat2 = ezsearch('(<REPEAT2>.*?</REPEAT2>)',s) +	repeat3 = ezsearch('(<REPEAT3>.*?</REPEAT3>)',s) +	dic = { 'STARTDATE': startdate, 'ENDDATE': enddate, 'WIKI_ROOTPATH': wiki_rootpath, +		'SYSINFO': sysinfo, 'SYSID':sysid,  +		'NUMTESTS':len(tests), 'NUMPASSED':len(passed_tests), 'PERCENTPASSED':percent } +	for key in dic.keys(): +		s = s.replace(key,str(dic[key])) + +	for t in tests_to_report: +		if t.type=='txt': +			newchunk = re.sub('FTESTNAME',t.fullname,repeat2) +			newchunk = newchunk.replace('TESTLOG',t.fulltestlog) +			s = s.replace(repeat2, newchunk+repeat2) +		elif t.type=='png': +			tmp = t.actualfile.replace(builddir,'') +			wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid) +			tmp = t.expectedfile.replace(os.path.dirname(builddir),'') +			wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid) +			imgs[wikiname_e] = t.expectedfile_data +			if t.actualfile:  +				actualfile_wiki = '[[File:'+wikiname_a+'|250px]]' +				imgs[wikiname_a] = t.actualfile_data +			else: +				actualfile_wiki = 'No image generated.' +			newchunk = re.sub('FTESTNAME',t.fullname,repeat1) +			newchunk = newchunk.replace('ACTUALFILE_WIKI',actualfile_wiki) +			newchunk = newchunk.replace('EXPECTEDFILE',wikiname_e) +			newchunk = newchunk.replace('TESTLOG',t.fulltestlog) +			s = s.replace(repeat1, newchunk+repeat1) + +	makefiles_wikinames = {} +	for mf in sorted(makefiles.keys()): +		tmp = mf.replace('CMakeFiles','').replace('.dir','') +		wikiname = wikify_filename(tmp,wiki_rootpath,sysid) +		newchunk = re.sub('MAKEFILE_NAME',wikiname,repeat3) +		s = s.replace(repeat3, newchunk+repeat3) +		makefiles_wikinames[mf] = wikiname + +	s = s.replace(repeat1,'') +	s = s.replace(repeat2,'') +	s = s.replace(repeat3,'') +	s = re.sub('<REPEAT.*?>\n','',s) +	s = re.sub('</REPEAT.*?>','',s) + +	mainpage_wikiname = wiki_rootpath + '_' + sysid + '_test_report' +	txtpages[ mainpage_wikiname ] = s +	for mf in sorted(makefiles.keys()): +		txtpages[ makefiles_wikinames[ mf ] ] = '\n*Subreport from [['+mainpage_wikiname+']]\n\n\n<pre>\n'+makefiles[mf]+'\n</pre>' + +	return imgs, txtpages + +def tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles): +	# kludge. assume wiki stuff has alreayd run and dumped files properly +	head = '<html><head><title>'+wiki_rootpath+' test run for '+sysid +'</title></head><body>' +	tail = '</body></html>' + +	passed_tests = filter(lambda x: x.passed, tests) +	failed_tests = filter(lambda x: not x.passed, tests) +	try: percent = str(int(100.0*len(passed_tests) / len(tests))) +	except ZeroDivisionError: percent = 'n/a' + +	tests_to_report = tests +	if failed_only: tests_to_report = failed_tests + +	s='' + +	s+= '\n<pre>' +	s+= '\nSYSINFO\n'+ sysinfo +	s+= '\n</pre><p>' + +	s+= '\n<pre>' +	s+= '\nSTARTDATE: '+ startdate +	s+= '\nENDDATE: '+ enddate +	s+= '\nWIKI_ROOTPATH: '+ wiki_rootpath +	s+= '\nSYSID: '+sysid +	s+= '\nNUMTESTS: '+str(len(tests)) +	s+= '\nNUMPASSED: '+str(len(passed_tests)) +	s+= '\nPERCENTPASSED: '+ percent +	s+= '\n</pre>' + +	for t in tests_to_report: +		if t.type=='txt': +			s+='\n<pre>'+t.fullname+'</pre>\n' +			s+='<p><pre>'+t.fulltestlog+'</pre>\n\n' +		elif t.type=='png': +			tmp = t.actualfile.replace(builddir,'') +			wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid) +			tmp = t.expectedfile.replace(os.path.dirname(builddir),'') +			wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid) +			s+='<table>' +			s+='\n<tr><td colspan=2>'+t.fullname +			s+='\n<tr><td>Expected<td>Actual' +			s+='\n<tr><td><img src='+wikiname_e+' width=250/>' +			s+='\n    <td><img src='+wikiname_a+' width=250/>' +			s+='\n</table>' +			s+='\n<pre>' +			s+=t.fulltestlog +			s+='\n</pre>' + +	s+='\n\n<p>\n\n' +	makefiles_wikinames = {} +	for mf in sorted(makefiles.keys()): +		tmp = mf.replace('CMakeFiles','').replace('.dir','') +		wikiname = wikify_filename(tmp,wiki_rootpath,sysid) +		s += '\n<a href='+wikiname+'>'+wikiname+'</a><br>' +	s+='\n' + +	return head + s + tail + +def wiki_login(wikiurl,api_php_path,botname,botpass): +	site = mwclient.Site(wikiurl,api_php_path) +	site.login(botname,botpass) +	return site + +def wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikipgname): +	counter = 0 +	done = False +	descrip = 'test' +	time.sleep(1) +	while not done: +		try: +			print 'login',botname,'to',wikiurl +			site = wiki_login(wikiurl,api_php_path,botname,botpass) +			print 'uploading...', +			if wikipgname.endswith('png'): +				site.upload(filedata,wikipgname,descrip,ignore=True) +			else: +				page = site.Pages[wikipgname] +				text = page.edit() +				page.save(filedata) +			done = True +			print 'transfer ok' +		except Exception, e: +			print 'Error:', type(e),e +			counter += 1 +			if counter>maxretry:  +				print 'giving up. please try a different wiki site' +				done = True +			else: +				print 'wiki',wikiurl,'down. retrying in 15 seconds' +				time.sleep(15)	 + +def upload(wikiurl,api_php_path='/',wiki_rootpath='test', sysid='null', botname='cakebaby',botpass='anniew',wikidir='.',dryrun=True): +	wetrun = not dryrun +	if dryrun: print 'dry run' +	try: +		global mwclient +		import mwclient +	except: +		print 'please download mwclient 0.6.5 and unpack here:', os.getcwd() +		sys.exit() + +	if wetrun: site = wiki_login(wikiurl,api_php_path,botname,botpass) + +	wikifiles = os.listdir(wikidir) +	testreport_page = filter( lambda x: 'test_report' in x, wikifiles ) +	if (len(testreport_page)>1):  +		print 'multiple test reports found, please clean dir',wikidir +		sys.exit() + +	rootpage = testreport_page[0] +	print 'add',rootpage,' to main report page ',wiki_rootpath +	if wetrun: +		page = site.Pages[wiki_rootpath] +		text = page.edit() +		if not '[['+rootpage+']]' in text: +			page.save(text +'\n*[['+rootpage+']]\n') + +	wikifiles = os.listdir(wikidir) +	wikifiles = filter(lambda x: not x.endswith('html'), wikifiles) + +	print 'upload wiki pages:' +	for wikiname in wikifiles: +		filename = os.path.join(wikidir,wikiname) +		filedata = tryread(filename) +		print 'upload',len(filedata),'bytes from',wikiname +		if wetrun and len(filedata)>0:  +			wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikiname) +		if len(filedata)==0:  +			print 'cancelling empty upload' + +def findlogfile(builddir): +	logpath = os.path.join(builddir,'Testing','Temporary') +	logfilename = os.path.join(logpath,'LastTest.log.tmp') +	if not os.path.isfile(logfilename): +		logfilename = os.path.join(logpath,'LastTest.log') +	if not os.path.isfile(logfilename): +		print 'cant find and/or open logfile',logfilename +		sys.exit() +	return logpath, logfilename + +def main(): +	dry = False +	if verbose: print 'running test_pretty_print' +	if '--dryrun' in sys.argv: dry=True +	suffix = ezsearch('--suffix=(.*?) ',string.join(sys.argv)+' ') +	builddir = ezsearch('--builddir=(.*?) ',string.join(sys.argv)+' ') +	if builddir=='': builddir=os.getcwd() +	if verbose: print 'build dir set to', builddir + +	sysinfo, sysid = read_sysinfo(os.path.join(builddir,'sysinfo.txt')) +	makefiles = load_makefiles(builddir) +	logpath, logfilename = findlogfile(builddir) +	testlog = tryread(logfilename) +	startdate, tests, enddate = parselog(testlog) +	if verbose: +		print 'found sysinfo.txt,', +		print 'found', len(makefiles),'makefiles,', +		print 'found', len(tests),'test results' + +	imgs, txtpages = towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles) + +	wikidir = os.path.join(logpath,sysid+'_report') +	if verbose: print 'erasing files in',wikidir +	try: map(lambda x:os.remove(os.path.join(wikidir,x)), os.listdir(wikidir)) +	except: pass +	print 'writing',len(imgs),'images, ',len(txtpages)-1,'text pages, and index.html to:\n', ' .'+wikidir.replace(os.getcwd(),'') +	for pgname in sorted(imgs): trysave( os.path.join(wikidir,pgname), imgs[pgname]) +	for pgname in sorted(txtpages): trysave( os.path.join(wikidir,pgname), txtpages[pgname]) + +	htmldata = tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles) +	trysave( os.path.join(wikidir,'index.html'), htmldata ) + +	if '--upload' in sys.argv: +		upload(wikisite,wiki_api_path,wiki_rootpath,sysid,'openscadbot', +			'tobdacsnepo',wikidir,dryrun=dry) +		print 'upload attempt complete' + +	if verbose: print 'test_pretty_print complete' + +#wikisite = 'cakebaby.referata.com' +#wiki_api_path = '' +wikisite = 'cakebaby.wikia.com' +wiki_api_path = '/' +wiki_rootpath = 'OpenSCAD' +builddir = os.getcwd() # os.getcwd()+'/build' +verbose = False +maxretry = 10 + +if bool(os.getenv("TEST_GENERATE")): sys.exit(0) + +failed_only = False +if '--failed-only' in sys.argv: failed_only = True + +main() diff --git a/tests/yee_compare.cpp b/tests/yee_compare.cpp deleted file mode 100644 index 9de4720..0000000 --- a/tests/yee_compare.cpp +++ /dev/null @@ -1,681 +0,0 @@ -// modified from PerceptualDiff source for OpenSCAD, 2011 September - -#include "yee_compare.h" -#include "lodepng.h" -#include <cstdlib> -#include <cstring> -#include <cstdio> -#include <math.h> - -static const char* copyright =  -"PerceptualDiff version 1.1.1, Copyright (C) 2006 Yangli Hector Yee\n\ -PerceptualDiff comes with ABSOLUTELY NO WARRANTY;\n\ -This is free software, and you are welcome\n\ -to redistribute it under certain conditions;\n\ -See the GPL page for details: http://www.gnu.org/copyleft/gpl.html\n\n"; - -static const char *usage = -"PeceptualDiff image1.tif image2.tif\n\n\ -   Compares image1.tif and image2.tif using a perceptually based image metric\n\ -   Options:\n\ -\t-verbose       : Turns on verbose mode\n\ -\t-fov deg       : Field of view in degrees (0.1 to 89.9)\n\ -\t-threshold p	 : #pixels p below which differences are ignored\n\ -\t-gamma g       : Value to convert rgb into linear space (default 2.2)\n\ -\t-luminance l   : White luminance (default 100.0 cdm^-2)\n\ -\t-luminanceonly : Only consider luminance; ignore chroma (color) in the comparison\n\ -\t-colorfactor   : How much of color to use, 0.0 to 1.0, 0.0 = ignore color.\n\ -\t-downsample    : How many powers of two to down sample the image.\n\ -\t-output o.ppm  : Write difference to the file o.ppm\n\ -\n\ -\n Note: Input or Output files can also be in the PNG or JPG format or any format\ -\n that FreeImage supports.\ -\n"; - -CompareArgs::CompareArgs() -{ -	ImgA = NULL; -	ImgB = NULL; -	ImgDiff = NULL; -	Verbose = false; -	LuminanceOnly = false; -	FieldOfView = 45.0f; -	Gamma = 2.2f; -	ThresholdPixels = 100; -	Luminance = 100.0f; -   ColorFactor = 1.0f; -   DownSample = 0; -} - -CompareArgs::~CompareArgs() -{ -	if (ImgA) delete ImgA; -	if (ImgB) delete ImgB; -	if (ImgDiff) delete ImgDiff; -} - -bool CompareArgs::Parse_Args(int argc, char **argv) -{ -	if (argc < 3) { -		ErrorStr = copyright; -		ErrorStr += usage; -		return false; -	} -	int image_count = 0; -	const char* output_file_name = NULL; -	for (int i = 1; i < argc; i++) { -		if (strcmp(argv[i], "-fov") == 0) { -			if (++i < argc) { -				FieldOfView = (float) atof(argv[i]); -			} -		} else if (strcmp(argv[i], "-verbose") == 0) { -			Verbose = true; -		} else if (strcmp(argv[i], "-threshold") == 0) { -			if (++i < argc) { -				ThresholdPixels = atoi(argv[i]); -			} -		} else if (strcmp(argv[i], "-gamma") == 0) { -			if (++i < argc) { -				Gamma = (float) atof(argv[i]); -			} -		} else if (strcmp(argv[i], "-luminance") == 0) { -			if (++i < argc) { -				Luminance = (float) atof(argv[i]); -			} -		} else if (strcmp(argv[i], "-luminanceonly") == 0) { -			LuminanceOnly = true; -		} else if (strcmp(argv[i], "-colorfactor") == 0) { -			if (++i < argc) { -				ColorFactor = (float) atof(argv[i]); -			} -		} else if (strcmp(argv[i], "-downsample") == 0) { -			if (++i < argc) { -				DownSample = (int) atoi(argv[i]); -			} -		} else if (strcmp(argv[i], "-output") == 0) { -			if (++i < argc) { -				output_file_name = argv[i]; -			} -		} else if (image_count < 2) { -			RGBAImage* img = RGBAImage::ReadFromFile(argv[i]); -			if (!img) { -				ErrorStr = "FAIL: Cannot open "; -				ErrorStr += argv[i]; -				ErrorStr += "\n"; -				return false; -			} else { -				++image_count; -				if(image_count == 1) -					ImgA = img; -				else -					ImgB = img; -			} -		} else { -			fprintf(stderr, "Warning: option/file \"%s\" ignored\n", argv[i]); -		} -	} // i -	if(!ImgA || !ImgB) { -		ErrorStr = "FAIL: Not enough image files specified\n"; -		return false; -	} -   for (int i = 0; i < DownSample; i++) { -      if (Verbose) printf("Downsampling by %d\n", 1 << (i+1)); -      RGBAImage *tmp = ImgA->DownSample(); -      if (tmp) { -         delete ImgA; -         ImgA = tmp; -      } -      tmp = ImgB->DownSample(); -      if (tmp) { -         delete ImgB; -         ImgB = tmp; -      } -   } -	if(output_file_name) { -		ImgDiff = new RGBAImage(ImgA->Get_Width(), ImgA->Get_Height(), output_file_name); -	} -	return true; -} - -void CompareArgs::Print_Args() -{ -	printf("Field of view is %f degrees\n", FieldOfView); -	printf("Threshold pixels is %d pixels\n", ThresholdPixels); -	printf("The Gamma is %f\n", Gamma); -	printf("The Display's luminance is %f candela per meter squared\n", Luminance); -} - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -LPyramid::LPyramid(float *image, int width, int height) : -	Width(width), -	Height(height) -{ -	// Make the Laplacian pyramid by successively -	// copying the earlier levels and blurring them -	for (int i=0; i<MAX_PYR_LEVELS; i++) { -		if (i == 0) { -			Levels[i] = Copy(image); -		} else { -			Levels[i] = new float[Width * Height]; -			Convolve(Levels[i], Levels[i - 1]); -		} -	} -} - -LPyramid::~LPyramid() -{ -	for (int i=0; i<MAX_PYR_LEVELS; i++) { -		if (Levels[i]) delete Levels[i]; -	} -} - -float *LPyramid::Copy(float *img) -{ -	int max = Width * Height; -	float *out = new float[max]; -	for (int i = 0; i < max; i++) out[i] = img[i]; -	 -	return out; -} - -void LPyramid::Convolve(float *a, float *b) -// convolves image b with the filter kernel and stores it in a -{ -	int y,x,i,j,nx,ny; -	const float Kernel[] = {0.05f, 0.25f, 0.4f, 0.25f, 0.05f}; - -	for (y=0; y<Height; y++) { -		for (x=0; x<Width; x++) { -			int index = y * Width + x; -			a[index] = 0.0f; -			for (i=-2; i<=2; i++) { -				for (j=-2; j<=2; j++) { -					nx=x+i; -					ny=y+j; -					if (nx<0) nx=-nx; -					if (ny<0) ny=-ny; -					if (nx>=Width) nx=2*Width-nx-1; -					if (ny>=Height) ny=2*Height-ny-1; -					a[index] += Kernel[i+2] * Kernel[j+2] * b[ny * Width + nx]; -				}  -			} -		} -	} -} - -float LPyramid::Get_Value(int x, int y, int level) -{ -	int index = x + y * Width; -	int l = level; -	if (l > MAX_PYR_LEVELS) l = MAX_PYR_LEVELS; -	return Levels[level][index]; -} - - - -#ifndef M_PI -#define M_PI 3.14159265f -#endif - -/* -* Given the adaptation luminance, this function returns the -* threshold of visibility in cd per m^2 -* TVI means Threshold vs Intensity function -* This version comes from Ward Larson Siggraph 1997 -*/  - -float tvi(float adaptation_luminance) -{ -      // returns the threshold luminance given the adaptation luminance -      // units are candelas per meter squared - -      float log_a, r, result;  -      log_a = log10f(adaptation_luminance); - -      if (log_a < -3.94f) { -            r = -2.86f; -      } else if (log_a < -1.44f) { -            r = powf(0.405f * log_a + 1.6f , 2.18f) - 2.86f; -      } else if (log_a < -0.0184f) { -            r = log_a - 0.395f; -      } else if (log_a < 1.9f) { -            r = powf(0.249f * log_a + 0.65f, 2.7f) - 0.72f; -      } else { -            r = log_a - 1.255f; -      } - -      result = powf(10.0f , r);  - -      return result; - -}  - -// computes the contrast sensitivity function (Barten SPIE 1989) -// given the cycles per degree (cpd) and luminance (lum) -float csf(float cpd, float lum) -{ -	float a, b, result;  -	 -	a = 440.0f * powf((1.0f + 0.7f / lum), -0.2f); -	b = 0.3f * powf((1.0f + 100.0f / lum), 0.15f); -		 -	result = a * cpd * expf(-b * cpd) * sqrtf(1.0f + 0.06f * expf(b * cpd));  -	 -	return result;	 -} - -/* -* Visual Masking Function -* from Daly 1993 -*/ -float mask(float contrast) -{ -      float a, b, result; -      a = powf(392.498f * contrast,  0.7f); -      b = powf(0.0153f * a, 4.0f); -      result = powf(1.0f + b, 0.25f);  - -      return result; -}  - -// convert Adobe RGB (1998) with reference white D65 to XYZ -void AdobeRGBToXYZ(float r, float g, float b, float &x, float &y, float &z) -{ -	// matrix is from http://www.brucelindbloom.com/ -	x = r * 0.576700f + g * 0.185556f + b * 0.188212f; -	y = r * 0.297361f + g * 0.627355f + b * 0.0752847f; -	z = r * 0.0270328f + g * 0.0706879f + b * 0.991248f; -} - -void XYZToLAB(float x, float y, float z, float &L, float &A, float &B) -{ -	static float xw = -1; -	static float yw; -	static float zw; -	// reference white -	if (xw < 0) { -		AdobeRGBToXYZ(1, 1, 1, xw, yw, zw); -	} -	const float epsilon  = 216.0f / 24389.0f; -	const float kappa = 24389.0f / 27.0f; -	float f[3]; -	float r[3]; -	r[0] = x / xw; -	r[1] = y / yw; -	r[2] = z / zw; -	for (int i = 0; i < 3; i++) { -		if (r[i] > epsilon) { -			f[i] = powf(r[i], 1.0f / 3.0f); -		} else { -			f[i] = (kappa * r[i] + 16.0f) / 116.0f; -		} -	} -	L = 116.0f * f[1] - 16.0f; -	A = 500.0f * (f[0] - f[1]); -	B = 200.0f * (f[1] - f[2]); -} - -bool Yee_Compare(CompareArgs &args) -{ -	if ((args.ImgA->Get_Width() != args.ImgB->Get_Width()) || -		(args.ImgA->Get_Height() != args.ImgB->Get_Height())) { -		args.ErrorStr = "Image dimensions do not match\n"; -		return false; -	} -	 -	unsigned int i, dim; -	dim = args.ImgA->Get_Width() * args.ImgA->Get_Height(); -	bool identical = true; -	for (i = 0; i < dim; i++) { -		if (args.ImgA->Get(i) != args.ImgB->Get(i)) { -		  identical = false; -		  break; -		} -	} -	if (identical) { -		args.ErrorStr = "Images are binary identical\n"; -		return true; -	} -	 -	// assuming colorspaces are in Adobe RGB (1998) convert to XYZ -	float *aX = new float[dim]; -	float *aY = new float[dim]; -	float *aZ = new float[dim]; -	float *bX = new float[dim]; -	float *bY = new float[dim]; -	float *bZ = new float[dim]; -	float *aLum = new float[dim]; -	float *bLum = new float[dim]; -	 -	float *aA = new float[dim]; -	float *bA = new float[dim]; -	float *aB = new float[dim]; -	float *bB = new float[dim]; - -	if (args.Verbose) printf("Converting RGB to XYZ\n"); -	 -	unsigned int x, y, w, h; -	w = args.ImgA->Get_Width(); -	h = args.ImgA->Get_Height(); -	for (y = 0; y < h; y++) { -		for (x = 0; x < w; x++) { -			float r, g, b, l; -			i = x + y * w; -			r = powf(args.ImgA->Get_Red(i) / 255.0f, args.Gamma); -			g = powf(args.ImgA->Get_Green(i) / 255.0f, args.Gamma); -			b = powf(args.ImgA->Get_Blue(i) / 255.0f, args.Gamma);						 -			AdobeRGBToXYZ(r,g,b,aX[i],aY[i],aZ[i]);			 -			XYZToLAB(aX[i], aY[i], aZ[i], l, aA[i], aB[i]); -			r = powf(args.ImgB->Get_Red(i) / 255.0f, args.Gamma); -			g = powf(args.ImgB->Get_Green(i) / 255.0f, args.Gamma); -			b = powf(args.ImgB->Get_Blue(i) / 255.0f, args.Gamma);						 -			AdobeRGBToXYZ(r,g,b,bX[i],bY[i],bZ[i]); -			XYZToLAB(bX[i], bY[i], bZ[i], l, bA[i], bB[i]); -			aLum[i] = aY[i] * args.Luminance; -			bLum[i] = bY[i] * args.Luminance; -		} -	} -	 -	if (args.Verbose) printf("Constructing Laplacian Pyramids\n"); -	 -	LPyramid *la = new LPyramid(aLum, w, h); -	LPyramid *lb = new LPyramid(bLum, w, h); -	 -	float num_one_degree_pixels = (float) (2 * tan( args.FieldOfView * 0.5 * M_PI / 180) * 180 / M_PI); -	float pixels_per_degree = w / num_one_degree_pixels; -	 -	if (args.Verbose) printf("Performing test\n"); -	 -	float num_pixels = 1; -	unsigned int adaptation_level = 0; -	for (i = 0; i < MAX_PYR_LEVELS; i++) { -		adaptation_level = i; -		if (num_pixels > num_one_degree_pixels) break; -		num_pixels *= 2; -	} -	 -	float cpd[MAX_PYR_LEVELS]; -	cpd[0] = 0.5f * pixels_per_degree; -	for (i = 1; i < MAX_PYR_LEVELS; i++) cpd[i] = 0.5f * cpd[i - 1]; -	float csf_max = csf(3.248f, 100.0f); -	 -	float F_freq[MAX_PYR_LEVELS - 2]; -	for (i = 0; i < MAX_PYR_LEVELS - 2; i++) F_freq[i] = csf_max / csf( cpd[i], 100.0f); -	 -	unsigned int pixels_failed = 0; -	for (y = 0; y < h; y++) { -	  for (x = 0; x < w; x++) { -		int index = x + y * w; -		float contrast[MAX_PYR_LEVELS - 2]; -		float sum_contrast = 0; -		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) { -			float n1 = fabsf(la->Get_Value(x,y,i) - la->Get_Value(x,y,i + 1)); -			float n2 = fabsf(lb->Get_Value(x,y,i) - lb->Get_Value(x,y,i + 1)); -			float numerator = (n1 > n2) ? n1 : n2; -			float d1 = fabsf(la->Get_Value(x,y,i+2)); -			float d2 = fabsf(lb->Get_Value(x,y,i+2)); -			float denominator = (d1 > d2) ? d1 : d2; -			if (denominator < 1e-5f) denominator = 1e-5f; -			contrast[i] = numerator / denominator; -			sum_contrast += contrast[i]; -		} -		if (sum_contrast < 1e-5) sum_contrast = 1e-5f; -		float F_mask[MAX_PYR_LEVELS - 2]; -		float adapt = la->Get_Value(x,y,adaptation_level) + lb->Get_Value(x,y,adaptation_level); -		adapt *= 0.5f; -		if (adapt < 1e-5) adapt = 1e-5f; -		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) { -			F_mask[i] = mask(contrast[i] * csf(cpd[i], adapt));  -		} -		float factor = 0; -		for (i = 0; i < MAX_PYR_LEVELS - 2; i++) { -			factor += contrast[i] * F_freq[i] * F_mask[i] / sum_contrast; -		} -		if (factor < 1) factor = 1; -		if (factor > 10) factor = 10; -		float delta = fabsf(la->Get_Value(x,y,0) - lb->Get_Value(x,y,0)); -		bool pass = true; -		// pure luminance test -		if (delta > factor * tvi(adapt)) { -			pass = false; -		} else if (!args.LuminanceOnly) { -			// CIE delta E test with modifications -                        float color_scale = args.ColorFactor; -			// ramp down the color test in scotopic regions -			if (adapt < 10.0f) { -                          // Don't do color test at all. -                          color_scale = 0.0; -			} -			float da = aA[index] - bA[index]; -			float db = aB[index] - bB[index]; -			da = da * da; -			db = db * db; -			float delta_e = (da + db) * color_scale; -			if (delta_e > factor) { -				pass = false; -			} -		} -		if (!pass) { -			pixels_failed++; -			if (args.ImgDiff) { -				args.ImgDiff->Set(255, 0, 0, 255, index); -			} -		} else { -			if (args.ImgDiff) { -				args.ImgDiff->Set(0, 0, 0, 255, index); -			} -		} -	  } -	} -	 -	if (aX) delete[] aX; -	if (aY) delete[] aY; -	if (aZ) delete[] aZ; -	if (bX) delete[] bX; -	if (bY) delete[] bY; -	if (bZ) delete[] bZ; -	if (aLum) delete[] aLum; -	if (bLum) delete[] bLum; -	if (la) delete la; -	if (lb) delete lb; -	if (aA) delete aA; -	if (bA) delete bA; -	if (aB) delete aB; -	if (bB) delete bB; - -	char different[100]; -	sprintf(different, "%d pixels are different\n", pixels_failed); - -        // Always output image difference if requested. -	if (args.ImgDiff) { -		if (args.ImgDiff->WriteToFile(args.ImgDiff->Get_Name().c_str())) { -			args.ErrorStr += "Wrote difference image to "; -			args.ErrorStr+= args.ImgDiff->Get_Name(); -			args.ErrorStr += "\n"; -		} else { -			args.ErrorStr += "Could not write difference image to "; -			args.ErrorStr+= args.ImgDiff->Get_Name(); -			args.ErrorStr += "\n"; -		} -	} - -	if (pixels_failed < args.ThresholdPixels) { -		args.ErrorStr = "Images are perceptually indistinguishable\n"; -                args.ErrorStr += different; -		return true; -	} -	 -	args.ErrorStr = "Images are visibly different\n"; -	args.ErrorStr += different; -	 -	return false; -} - -RGBAImage* RGBAImage::DownSample() const { -   if (Width <=1 || Height <=1) return NULL; -   int nw = Width / 2; -   int nh = Height / 2; -   RGBAImage* img = new RGBAImage(nw, nh, Name.c_str()); -   for (int y = 0; y < nh; y++) { -      for (int x = 0; x < nw; x++) { -         int d[4]; -         // Sample a 2x2 patch from the parent image. -         d[0] = Get(2 * x + 0, 2 * y + 0); -         d[1] = Get(2 * x + 1, 2 * y + 0); -         d[2] = Get(2 * x + 0, 2 * y + 1); -         d[3] = Get(2 * x + 1, 2 * y + 1); -         int rgba = 0; -         // Find the average color. -         for (int i = 0; i < 4; i++) { -            int c = (d[0] >> (8 * i)) & 0xFF; -            c += (d[1] >> (8 * i)) & 0xFF; -            c += (d[2] >> (8 * i)) & 0xFF; -            c += (d[3] >> (8 * i)) & 0xFF; -            c /= 4; -            rgba |= (c & 0xFF) << (8 * i); -         } -         img->Set(x, y, rgba); -      } -   } -   return img; -} - - -bool RGBAImage::WriteToFile(const char* filename) -{ -	LodePNG::Encoder encoder; -	encoder.addText("Comment","lodepng"); -	encoder.getSettings().zlibsettings.windowSize = 2048; -	 - -/* -	const FREE_IMAGE_FORMAT fileType = FreeImage_GetFIFFromFilename(filename); -	if(FIF_UNKNOWN == fileType) -	{ -		printf("Can't save to unknown filetype %s\n", filename); -		return false; -	} - -	FIBITMAP* bitmap = FreeImage_Allocate(Width, Height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000); -	if(!bitmap) -	{ -		printf("Failed to create freeimage for %s\n", filename); -		return false; -	} - -	const unsigned int* source = Data; -	for( int y=0; y < Height; y++, source += Width ) -	{ -		unsigned int* scanline = (unsigned int*)FreeImage_GetScanLine(bitmap, Height - y - 1 ); -		memcpy(scanline, source, sizeof(source[0]) * Width); -	}	 -	 -	FreeImage_SetTransparent(bitmap, false); -	FIBITMAP* converted = FreeImage_ConvertTo24Bits(bitmap); -	 -	 -	const bool result = !!FreeImage_Save(fileType, converted, filename); -	if(!result) -		printf("Failed to save to %s\n", filename); -	 -	FreeImage_Unload(converted); -	FreeImage_Unload(bitmap); -	return result; -*/ -	return true; -} - -RGBAImage* RGBAImage::ReadFromFile(const char* filename) -{ -  unsigned char* buffer; -  unsigned char* image; -  size_t buffersize, imagesize, i; -  LodePNG_Decoder decoder; -   -  LodePNG_loadFile(&buffer, &buffersize, filename); /*load the image file with given filename*/ -  LodePNG_Decoder_init(&decoder); -  LodePNG_Decoder_decode(&decoder, &image, &imagesize, buffer, buffersize); /*decode the png*/ -   -  /*load and decode*/ -  /*if there's an error, display it, otherwise display information about the image*/ -  if(decoder.error) printf("error %u: %s\n", decoder.error, LodePNG_error_text(decoder.error)); - -  int w = decoder.infoPng.width; -  int h = decoder.infoPng.height; -   - -  RGBAImage* result = new RGBAImage(w, h, filename); -  // Copy the image over to our internal format, FreeImage has the scanlines bottom to top though. -  unsigned int* dest = result->Data; -  memcpy(dest, (void *)image, h*w*4); - -  /*cleanup decoder*/ -  free(image); -  free(buffer); -  LodePNG_Decoder_cleanup(&decoder); - -  return result; -/* -	const FREE_IMAGE_FORMAT fileType = FreeImage_GetFileType(filename); -	if(FIF_UNKNOWN == fileType) -	{ -		printf("Unknown filetype %s\n", filename); -		return 0; -	} -	 -	FIBITMAP* freeImage = 0; -	if(FIBITMAP* temporary = FreeImage_Load(fileType, filename, 0)) -	{ -		freeImage = FreeImage_ConvertTo32Bits(temporary); -		FreeImage_Unload(temporary); -	} -	if(!freeImage) -	{ -		printf( "Failed to load the image %s\n", filename); -		return 0; -	} - -	const int w = FreeImage_GetWidth(freeImage); -	const int h = FreeImage_GetHeight(freeImage); - -	RGBAImage* result = new RGBAImage(w, h, filename); -	// Copy the image over to our internal format, FreeImage has the scanlines bottom to top though. -	unsigned int* dest = result->Data; -	for( int y=0; y < h; y++, dest += w ) -	{ -		const unsigned int* scanline = (const unsigned int*)FreeImage_GetScanLine(freeImage, h - y - 1 ); -		memcpy(dest, scanline, sizeof(dest[0]) * w); -	}	 - -	FreeImage_Unload(freeImage); -	return result; -	return NULL; -*/ -} - - -int main(int argc, char **argv) -{ -	CompareArgs args; -	 -	if (!args.Parse_Args(argc, argv)) { -		printf("%s", args.ErrorStr.c_str()); -		return -1; -	} else { -		if (args.Verbose) args.Print_Args(); -	} -	 -	const bool passed = Yee_Compare(args); -	if (passed) { -		if(args.Verbose) -			printf("PASS: %s\n", args.ErrorStr.c_str()); -	} else { -		printf("FAIL: %s\n", args.ErrorStr.c_str()); -	} - -	return passed ? 0 : 1; -} - diff --git a/tests/yee_compare.h b/tests/yee_compare.h deleted file mode 100644 index 041ae4c..0000000 --- a/tests/yee_compare.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _yee_compare_h -#define _yee_compare_h - -// source code modified for OpenSCAD, Sept 2011 -// original copyright notice follows: -/* -Metric -RGBAImage.h -Comapre Args -Laplacian Pyramid -Copyright (C) 2006 Yangli Hector Yee - -This program is free software; you can redistribute it and/or modify it under the terms of the -GNU General Public License as published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program; -if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <string> - -class RGBAImage; - -// Args to pass into the comparison function -class CompareArgs -{ -public: -	CompareArgs(); -	~CompareArgs(); -	bool Parse_Args(int argc, char **argv);	 -	void Print_Args(); -	 -	RGBAImage		*ImgA;				// Image A -	RGBAImage		*ImgB;				// Image B -	RGBAImage		*ImgDiff;			// Diff image -	bool			Verbose;			// Print lots of text or not -	bool			LuminanceOnly;		// Only consider luminance; ignore chroma channels in the comparison. -	float			FieldOfView;		// Field of view in degrees -	float			Gamma;				// The gamma to convert to linear color space -	float			Luminance;			// the display's luminance -	unsigned int	ThresholdPixels;	// How many pixels different to ignore -	std::string		ErrorStr;			// Error string -  // How much color to use in the metric. -  // 0.0 is the same as LuminanceOnly = true, -  // 1.0 means full strength. -  float ColorFactor; -  // How much to down sample image before comparing, in powers of 2. -  int DownSample; -}; - -#define MAX_PYR_LEVELS 8 - -class LPyramid -{ -public:	 -	LPyramid(float *image, int width, int height); -	virtual ~LPyramid(); -	float Get_Value(int x, int y, int level); -protected: -	float *Copy(float *img); -	void Convolve(float *a, float *b); -	 -	// Succesively blurred versions of the original image -	float *Levels[MAX_PYR_LEVELS]; - -	int Width; -	int Height; -}; - -class CompareArgs; - -// Image comparison metric using Yee's method -// References: A Perceptual Metric for Production Testing, Hector Yee, Journal of Graphics Tools 2004 -bool Yee_Compare(CompareArgs &args); - -/** Class encapsulating an image containing R,G,B,A channels. - * - * Internal representation assumes data is in the ABGR format, with the RGB - * color channels premultiplied by the alpha value.  Premultiplied alpha is - * often also called "associated alpha" - see the tiff 6 specification for some - * discussion - http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf - * - */ -class RGBAImage -{ -	RGBAImage(const RGBAImage&); -	RGBAImage& operator=(const RGBAImage&); -public: -	RGBAImage(int w, int h, const char *name = 0) -	{ -		Width = w; -		Height = h; -		if (name) Name = name; -		Data = new unsigned int[w * h]; -	}; -	~RGBAImage() { if (Data) delete[] Data; } -	unsigned char Get_Red(unsigned int i) { return (Data[i] & 0xFF); } -	unsigned char Get_Green(unsigned int i) { return ((Data[i]>>8) & 0xFF); } -	unsigned char Get_Blue(unsigned int i) { return ((Data[i]>>16) & 0xFF); } -	unsigned char Get_Alpha(unsigned int i) { return ((Data[i]>>24) & 0xFF); } -	void Set(unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned int i) -	{ Data[i] = r | (g << 8) | (b << 16) | (a << 24); } -	int Get_Width(void) const { return Width; } -	int Get_Height(void) const { return Height; } -	void Set(int x, int y, unsigned int d) { Data[x + y * Width] = d; } -	unsigned int Get(int x, int y) const { return Data[x + y * Width]; } -	unsigned int Get(int i) const { return Data[i]; } -	const std::string &Get_Name(void) const { return Name; } -   RGBAImage* DownSample() const; -	 -	bool WriteToFile(const char* filename); -	static RGBAImage* ReadFromFile(const char* filename); -	 -protected: -	int Width; -	int Height; -	std::string Name; -	unsigned int *Data; -}; - -#endif | 
