diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2626072335..26fa99157e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,6 +1,11 @@
 name: LAGraph CI
 
-on: [push, pull_request]
+on:
+  workflow_dispatch:
+  push:
+    branches-ignore:
+      - '**/*dev2'
+  pull_request:
 
 jobs:
   linux:
diff --git a/Acknowledgments.txt b/Acknowledgments.txt
index ecb4359f84..815f4e01f9 100644
--- a/Acknowledgments.txt
+++ b/Acknowledgments.txt
@@ -16,7 +16,7 @@ THIS WORK IS FUNDED IN PART BY:
 THIS WORK BUILDS UPON THE FOLLOWING PRIOR WORKS:
 1.  SuiteSparse:GraphBLAS, 
     (http://faculty.cse.tamu.edu/davis/GraphBLAS.html) 
-    Copyright 2017-2022  Timothy A. Davis (Author), AldenMath.com.
+    Copyright 2017-2023  Timothy A. Davis (Author), AldenMath.com.
     By Tim Davis, Texas A&M University. Note that while SuiteSparse:GraphBLAS
     is itself under the Apache 2 license, any contributions derived from
     SuiteSparse:GraphBLAS and incorporated by the Author into LAGraph are
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfe16c3da5..975582e662 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,31 +36,45 @@
 # get the version
 #-------------------------------------------------------------------------------
 
-cmake_minimum_required ( VERSION 3.13 )
+cmake_minimum_required ( VERSION 3.20 ) # LAGraph can be built stand-alone
 
-set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
-    ${CMAKE_SOURCE_DIR}/cmake_modules
-    ${CMAKE_SOURCE_DIR}/../cmake_modules
-    ${CMAKE_SOURCE_DIR}/../SuiteSparse/cmake_modules
-    )
+# version of LAGraph
+set ( LAGraph_DATE "Dec 30, 2023" )
+set ( LAGraph_VERSION_MAJOR 1 CACHE STRING "" FORCE )
+set ( LAGraph_VERSION_MINOR 1 CACHE STRING "" FORCE )
+set ( LAGraph_VERSION_SUB   0 CACHE STRING "" FORCE )
 
-cmake_policy ( SET CMP0042 NEW )
-cmake_policy ( SET CMP0048 NEW )
-set ( CMAKE_MACOSX_RPATH TRUE )
+message ( STATUS "Building LAGraph version: v"
+    ${LAGraph_VERSION_MAJOR}.
+    ${LAGraph_VERSION_MINOR}.
+    ${LAGraph_VERSION_SUB} " (" ${LAGraph_DATE} ")" )
 
-# version of LAGraph
-set ( LAGraph_DATE "Aug 2, 2023" )
-set ( LAGraph_VERSION_MAJOR 1 )
-set ( LAGraph_VERSION_MINOR 0 )
-set ( LAGraph_VERSION_SUB   2 )
+#-------------------------------------------------------------------------------
+# define the project
+#-------------------------------------------------------------------------------
 
-project ( lagraph
+project ( LAGraph
           VERSION "${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}" )
 
+#-------------------------------------------------------------------------------
+# SuiteSparse policies
+#-------------------------------------------------------------------------------
+
+set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    ${PROJECT_SOURCE_DIR}/cmake_modules
+    ${PROJECT_SOURCE_DIR}/../cmake_modules
+    ${PROJECT_SOURCE_DIR}/../SuiteSparse_config/cmake_modules
+    )
+
+include ( SuiteSparsePolicy )
+
+enable_language ( C )
+
 # configure LAGraph.h with the LAGraph date and version
 configure_file (
     "config/LAGraph.h.in"
-    "${PROJECT_SOURCE_DIR}/include/LAGraph.h" )
+    "${PROJECT_SOURCE_DIR}/include/LAGraph.h"
+    NEWLINE_STYLE LF )
 
 #-------------------------------------------------------------------------------
 # code coverage and build type
@@ -73,30 +87,28 @@ configure_file (
 #   make test_coverage
 
 if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
-	if ( COVERAGE )
-                message ( STATUS "============== Code coverage enabled ===============" )
-		set ( CMAKE_BUILD_TYPE Debug )
-                # On the Mac, you need gcov-11 from homebrew (part of gcc-11):
-                # and uncomment this line:
-                # set ( GCOV_PATH /usr/local/bin/gcov-11)
-		include ( CodeCoverage )
-
-		append_coverage_compiler_flags ( )
-
-		# turn off optimization for non-skewed coverage reports
-		set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -DCOVERAGE" )
-		set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0" )
-
-		setup_target_for_coverage_lcov (
-			NAME test_coverage
-			EXECUTABLE ctest
-			DEPENDENCIES ${PROJECT_NAME}
-			BASE_DIRECTORY "."
-			NO_DEMANGLE TRUE
-                        EXCLUDE "*/benchmark/*" "deps/json*/*"
-                            "src/test/include/acutest.h"
-		)
-	endif ( )
+    if ( COVERAGE )
+        message ( STATUS "============== Code coverage enabled ===============" )
+        set ( CMAKE_BUILD_TYPE Debug )
+        # On the Mac, you need gcov-11 from homebrew (part of gcc-11):
+        # and uncomment this line:
+        # set ( GCOV_PATH /usr/local/bin/gcov-11)
+        include ( CodeCoverage )
+
+        append_coverage_compiler_flags ( )
+
+        # turn off optimization for non-skewed coverage reports
+        set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -DCOVERAGE" )
+
+        setup_target_for_coverage_lcov (
+            NAME test_coverage
+            EXECUTABLE ctest
+            DEPENDENCIES ${PROJECT_NAME}
+            BASE_DIRECTORY "."
+            NO_DEMANGLE TRUE
+            EXCLUDE "*/benchmark/*" "deps/json*/*" "src/test/include/acutest.h"
+            )
+    endif ( )
 endif ( )
 
 # For development only, not for end-users:
@@ -110,37 +122,80 @@ endif ( )
 # Find the GraphBLAS installation
 #-------------------------------------------------------------------------------
 
-# If GraphBLAS is not in a standard installation location, either
-#     export GRAPHBLAS_ROOT <path>
-# or
-#     GRAPHBLAS_ROOT=<path> cmake ..
-# or uncomment the next line:
-# set ( ENV{GRAPHBLAS_ROOT} ${CMAKE_SOURCE_DIR}/../GraphBLAS )
-message ( STATUS "GraphBLAS_ROOT: ${GraphBLAS_ROOT} $ENV{GraphBLAS_ROOT}" )
-message ( STATUS "GRAPHBLAS_ROOT: ${GRAPHBLAS_ROOT} $ENV{GRAPHBLAS_ROOT}" )
-find_package (GraphBLAS 7.0.1 REQUIRED MODULE)
+if ( SUITESPARSE_ROOT_CMAKELISTS )
+
+    if ( TARGET GraphBLAS )
+        add_library ( GraphBLAS::GraphBLAS ALIAS GraphBLAS )
+    else ( )
+        add_library ( GraphBLAS::GraphBLAS ALIAS GraphBLAS_static )
+    endif ( )
+    if ( TARGET GraphBLAS_static )
+        add_library ( GraphBLAS::GraphBLAS_static ALIAS GraphBLAS_static )
+    endif ( )
+
+else ( )
+
+    # If GraphBLAS is not in a standard installation location, either
+    #     export GRAPHBLAS_ROOT <path>
+    # or
+    #     GRAPHBLAS_ROOT=<path> cmake ..
+    # or uncomment the next line:
+    # set ( ENV{GRAPHBLAS_ROOT} ${PROJECT_SOURCE_DIR}/../GraphBLAS )
+
+    # The ../GraphBLAS folder is considered by default, if it exists.
+
+#   message ( STATUS "GraphBLAS_ROOT: ${GraphBLAS_ROOT} $ENV{GraphBLAS_ROOT}" )
+#   message ( STATUS "GRAPHBLAS_ROOT: ${GRAPHBLAS_ROOT} $ENV{GRAPHBLAS_ROOT}" )
+
+    # No package version is explicitly stated here; an arbitrary GraphBLAS
+    # library can have any version number.  For SuiteSparse:GraphBLAS, LAGraph
+    # requires v7.1.0 or later, which is checked in LAGraph.h.
+    find_package ( GraphBLAS MODULE REQUIRED )
+
+endif ( )
 
 #-------------------------------------------------------------------------------
 # determine what user threading model to use
 #-------------------------------------------------------------------------------
 
+option ( LAGRAPH_USE_OPENMP "ON: Use OpenMP in LAGraph if available.  OFF: Do not use OpenMP.  (Default: SUITESPARSE_USE_OPENMP)" ${SUITESPARSE_USE_OPENMP} )
+if ( NOT SUITESPARSE_USE_OPENMP )
+    set ( LAGRAPH_USE_OPENMP "OFF" CACHE STRING "" FORCE )
+endif ( )
 if ( COVERAGE )
+    set ( LAGRAPH_USE_OPENMP "OFF" CACHE STRING "" FORCE ) # OK: test coverage is enabled
     message ( STATUS "OpenMP disabled for test coverage" )
 else ( )
-    include ( FindOpenMP  )
-    include ( FindThreads )
-    if ( OPENMP_FOUND )
-        set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS} " )
+    if ( LAGRAPH_USE_OPENMP )
+        find_package ( OpenMP GLOBAL )
+        if ( OpenMP_C_FOUND AND BUILD_STATIC_LIBS )
+            list ( APPEND LAGRAPH_STATIC_LIBS ${OpenMP_C_LIBRARIES} )
+        endif ( )
+        find_package ( Threads )
+    else ( )
+        set ( OpenMP_C_FOUND OFF )
     endif ( )
 endif ( )
 
+if ( OpenMP_C_FOUND )
+    set ( LAGRAPH_HAS_OPENMP ON )
+else ( )
+    set ( LAGRAPH_HAS_OPENMP OFF )
+endif ( )
+message ( STATUS "LAGraph has OpenMP: ${LAGRAPH_HAS_OPENMP}" )
+
+# check for strict usage
+if ( SUITESPARSE_USE_STRICT AND LAGRAPH_USE_OPENMP AND NOT LAGRAPH_HAS_OPENMP )
+    message ( FATAL_ERROR "OpenMP required for LAGraph but not found" )
+endif ( )
+
 #-------------------------------------------------------------------------------
 # report status
 #-------------------------------------------------------------------------------
 
 message ( STATUS "CMAKE build type:          " ${CMAKE_BUILD_TYPE} )
-message ( STATUS "CMAKE source directory:    " ${CMAKE_SOURCE_DIR} )
-message ( STATUS "CMAKE build directory:     " ${CMAKE_BINARY_DIR} )
+message ( STATUS "CMAKE source directory:    " ${PROJECT_SOURCE_DIR} )
+message ( STATUS "CMAKE build directory:     " ${PROJECT_BINARY_DIR} )
 
 if ( ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
     message ( STATUS "CMAKE C Flags debug:       " ${CMAKE_C_FLAGS_DEBUG} )
@@ -152,34 +207,27 @@ message ( STATUS "CMAKE compiler ID:         " ${CMAKE_C_COMPILER_ID} )
 message ( STATUS "CMAKE thread library:      " ${CMAKE_THREAD_LIBS_INIT} )
 message ( STATUS "CMAKE have pthreads:       " ${CMAKE_USE_PTHREADS_INIT}  )
 message ( STATUS "CMAKE have Win32 pthreads: " ${CMAKE_USE_WIN32_THREADS_INIT} )
-message ( STATUS "CMAKE have OpenMP:         " ${OPENMP_FOUND} )
+message ( STATUS "CMAKE have OpenMP:         " ${OPENMP_C_FOUND} )
 
 #-------------------------------------------------------------------------------
 # include directories for LAGraph library
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/include
-                      ${CMAKE_SOURCE_DIR}/src/utility
-                      ${CMAKE_SOURCE_DIR}/test/include
-                      ${GRAPHBLAS_INCLUDE_DIR} )
-include_directories ( "/usr/local/include" )
+include_directories ( ${PROJECT_SOURCE_DIR}/include
+                      ${PROJECT_SOURCE_DIR}/src/utility
+                      ${PROJECT_SOURCE_DIR}/test/include )
 
 # tell LAGraph where to find its own source (for LAGraph/data files)
-set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLGDIR=${CMAKE_SOURCE_DIR}" )
+set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLGDIR=${PROJECT_SOURCE_DIR}" )
+# set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O" )
 
 #-------------------------------------------------------------------------------
 # compiler options
 #-------------------------------------------------------------------------------
 
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED True)
-
 # check which compiler is being used.  If you need to make
 # compiler-specific modifications, here is the place to do it.
 if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
-    # cmake 2.8 workaround: gcc needs to be told to do ANSI C11.
-    # cmake 3.0 doesn't have this problem.
-    set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -std=c11 -lm -Wno-pragmas " )
     # check all warnings:
 #   set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -Werror " )
     # set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -g " )
@@ -187,11 +235,9 @@ if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
     #    message ( FATAL_ERROR "gcc version must be at least 4.9" )
     #endif ( )
 elseif ( "${CMAKE_C_COMPILER_ID}" STREQUAL "Intel" )
-    # options for icc: also needs -std=c11
     # note that -g can be used, for VTune.  Comment out the following line
     # to compile without -g.
     # set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -g " )
-    set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -std=c11 " )
     # check all warnings:
 #   set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -w3 " )
     #if ( CMAKE_C_COMPILER_VERSION VERSION_LESS 18.0 )
@@ -199,7 +245,7 @@ elseif ( "${CMAKE_C_COMPILER_ID}" STREQUAL "Intel" )
     #endif ( )
 elseif ( "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
     # options for clang
-    set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -O3 -std=c11 " )
+    set ( CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -O3 " )
     #if ( CMAKE_C_COMPILER_VERSION VERSION_LESS 3.3 )
     #    message ( FATAL_ERROR "clang version must be at least 3.3" )
     #endif ( )
@@ -207,8 +253,7 @@ elseif ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
     # options for MicroSoft Visual Studio
 elseif ( "${CMAKE_C_COMPILER_ID}" STREQUAL "PGI" )
     # options for PGI pgcc compiler
-    set ( CMAKE_C_FLAGS    "${CMAKE_C_FLAGS} -acc -Minfo=accel -Mcuda -Mnoopenmp -noswitcherror -c11 -lm -fPIC " )
-    set ( CMAKE_CXX_FLAGS  "${CMAKE_C_FLAGS} -acc -Minfo=accel -Mcuda -Mnoopenmp -D__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1 -noswitcherror --c++11 -lm -fPIC " )
+    set ( CMAKE_C_FLAGS    "${CMAKE_C_FLAGS} -acc -Minfo=accel -Mcuda -Mnoopenmp -noswitcherror -fPIC " )
 endif ( )
 
 if ( ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
@@ -238,11 +283,7 @@ message ( STATUS "CMAKE C flags: " ${CMAKE_C_FLAGS} )
 # enable testing and add subdirectories
 #-------------------------------------------------------------------------------
 
-# allow ctest to find the binaries:
-set ( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} )
-set ( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} )
-
-enable_testing ( )
+include ( CTest )
 
 add_subdirectory ( src )
 add_subdirectory ( experimental )
@@ -254,17 +295,128 @@ endif ( )
 # LAGraph installation location
 #-------------------------------------------------------------------------------
 
-# install in ${CMAKE_INSTALL_PREFIX}/lib and ${CMAKE_INSTALL_PREFIX}/include.
-# Requires "sudo make install" if this is /usr/local (default).
+include ( CMakePackageConfigHelpers )
 
-message ( STATUS "Installation in: ${CMAKE_INSTALL_PREFIX}" )
-include ( GNUInstallDirs )
+if ( BUILD_SHARED_LIBS )
+    install ( TARGETS LAGraph LAGraphX
+        EXPORT LAGraphTargets
+        LIBRARY DESTINATION ${SUITESPARSE_LIBDIR}
+        ARCHIVE DESTINATION ${SUITESPARSE_LIBDIR}
+        RUNTIME DESTINATION ${SUITESPARSE_BINDIR}
+        PUBLIC_HEADER DESTINATION ${SUITESPARSE_INCLUDEDIR} )
+endif ( )
 
-install ( TARGETS lagraph lagraphx
-    LIBRARY       DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} )
+if ( BUILD_STATIC_LIBS )
+    install ( TARGETS LAGraph_static LAGraphX_static
+        EXPORT LAGraphTargets
+        ARCHIVE DESTINATION ${SUITESPARSE_LIBDIR}
+        PUBLIC_HEADER DESTINATION ${SUITESPARSE_INCLUDEDIR} )
+endif ( )
 
-install ( TARGETS lagraph_static lagraphx_static
-    ARCHIVE       DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} )
 
+# create (temporary) export target file during build
+export ( EXPORT LAGraphTargets
+    NAMESPACE SuiteSparse::
+    FILE ${CMAKE_CURRENT_BINARY_DIR}/LAGraphTargets.cmake )
+
+# install export target, config and version files for find_package
+install ( EXPORT LAGraphTargets
+    NAMESPACE SuiteSparse::
+    DESTINATION ${SUITESPARSE_PKGFILEDIR}/cmake/LAGraph )
+
+# generate config file to be used in common build tree
+set ( SUITESPARSE_IN_BUILD_TREE ON )
+configure_package_config_file (
+    config/LAGraphConfig.cmake.in
+    ${CMAKE_CURRENT_BINARY_DIR}/LAGraphConfig.cmake
+    INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/LAGraphConfig.cmake )
+
+# generate config file to be installed
+set ( SUITESPARSE_IN_BUILD_TREE OFF )
+configure_package_config_file (
+    config/LAGraphConfig.cmake.in
+    ${CMAKE_CURRENT_BINARY_DIR}/target/LAGraphConfig.cmake
+    INSTALL_DESTINATION ${SUITESPARSE_PKGFILEDIR}/cmake/LAGraph )
+
+write_basic_package_version_file (
+    ${CMAKE_CURRENT_BINARY_DIR}/LAGraphConfigVersion.cmake
+    COMPATIBILITY SameMajorVersion )
+
+install ( FILES
+    ${CMAKE_CURRENT_BINARY_DIR}/target/LAGraphConfig.cmake
+    ${CMAKE_CURRENT_BINARY_DIR}/LAGraphConfigVersion.cmake
+    ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindGraphBLAS.cmake
+    DESTINATION ${SUITESPARSE_PKGFILEDIR}/cmake/LAGraph )
+
+#-------------------------------------------------------------------------------
+# create pkg-config file
+#-------------------------------------------------------------------------------
+
+if ( NOT MSVC )
+    if ( BUILD_STATIC_LIBS )
+        if ( NOT WIN32 )
+            list ( APPEND LAGRAPH_STATIC_LIBS "m" )
+        endif ( )
+    endif ( )
+    # This might be something like:
+    #   /usr/lib/libgomp.so;/usr/lib/libpthread.a;m
+    # convert to -l flags for pkg-config, i.e.: "-lgomp -lpthread -lm"
+    set ( LAGRAPH_STATIC_LIBS_LIST ${LAGRAPH_STATIC_LIBS} )
+    set ( LAGRAPH_STATIC_LIBS "" )
+    foreach ( _lib ${LAGRAPH_STATIC_LIBS_LIST} )
+        string ( FIND ${_lib} "." _pos REVERSE )
+        if ( ${_pos} EQUAL "-1" )
+            set ( LAGRAPH_STATIC_LIBS "${LAGRAPH_STATIC_LIBS} -l${_lib}" )
+            continue ()
+        endif ( )
+        set ( _kinds "SHARED" "STATIC" )
+        if ( WIN32 )
+            list ( PREPEND _kinds "IMPORT" )
+        endif ( )
+        foreach ( _kind IN LISTS _kinds )
+            set ( _regex ".*\\/(lib)?([^\\.]*)(${CMAKE_${_kind}_LIBRARY_SUFFIX})" )
+            if ( ${_lib} MATCHES ${_regex} )
+                string ( REGEX REPLACE ${_regex} "\\2" _libname ${_lib} )
+                if ( NOT "${_libname}" STREQUAL "" )
+                    set ( LAGRAPH_STATIC_LIBS "${LAGRAPH_STATIC_LIBS} -l${_libname}" )
+                    break ()
+                endif ( )
+            endif ( )
+        endforeach ( )
+    endforeach ( )
+    if ( BUILD_STATIC_LIBS )
+        set ( LAGRAPH_STATIC_LIBS "-l$<TARGET_FILE_BASE_NAME:GraphBLAS::GraphBLAS> ${LAGRAPH_STATIC_LIBS}" )
+    endif ( )
+
+    set ( prefix "${CMAKE_INSTALL_PREFIX}" )
+    set ( exec_prefix "\${prefix}" )
+    cmake_path ( IS_ABSOLUTE SUITESPARSE_LIBDIR SUITESPARSE_LIBDIR_IS_ABSOLUTE )
+    if (SUITESPARSE_LIBDIR_IS_ABSOLUTE)
+        set ( libdir "${SUITESPARSE_LIBDIR}")
+    else ( )
+        set ( libdir "\${exec_prefix}/${SUITESPARSE_LIBDIR}")
+    endif ( )
+    cmake_path ( IS_ABSOLUTE SUITESPARSE_INCLUDEDIR SUITESPARSE_INCLUDEDIR_IS_ABSOLUTE )
+    if (SUITESPARSE_INCLUDEDIR_IS_ABSOLUTE)
+        set ( includedir "${SUITESPARSE_INCLUDEDIR}")
+    else ( )
+        set ( includedir "\${prefix}/${SUITESPARSE_INCLUDEDIR}")
+    endif ( )
+    if ( BUILD_SHARED_LIBS )
+        set ( SUITESPARSE_LIB_BASE_NAME $<TARGET_FILE_BASE_NAME:LAGraph> )
+    else ( )
+        set ( SUITESPARSE_LIB_BASE_NAME $<TARGET_FILE_BASE_NAME:LAGraph_static> )
+    endif ( )
+    configure_file (
+        config/LAGraph.pc.in
+        LAGraph.pc.out
+        @ONLY
+        NEWLINE_STYLE LF )
+    file ( GENERATE
+        OUTPUT LAGraph.pc
+        INPUT ${CMAKE_CURRENT_BINARY_DIR}/LAGraph.pc.out
+        NEWLINE_STYLE LF )
+    install ( FILES
+        ${CMAKE_CURRENT_BINARY_DIR}/LAGraph.pc
+        DESTINATION ${SUITESPARSE_PKGFILEDIR}/pkgconfig )
+endif ( )
diff --git a/ChangeLog b/ChangeLog
index fb7e628499..c88d5f479d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Dec 30, 2023: version 1.1.0
+
+    * major change to build system: by Markus Mützel
+    * port: to 32-bit systems
+
 Version 1.0.2: Aug 2, 2023
 
     * port: removed GxB_SelectOp so LAGraph v1.0.2 can be compiled with
diff --git a/Contributors.txt b/Contributors.txt
index 4e2f47c319..367ebe60fd 100644
--- a/Contributors.txt
+++ b/Contributors.txt
@@ -22,9 +22,10 @@ Contributors (in alphabetical order):
     Tze Meng Low,      Carnegie Mellon University
     Tim Mattson,       Intel
     Scott McMillan,    Carnegie Mellon University
+    Markus Muetzel,
     Michel Pelletier,  Graphegon
     Gabor Szarnyas,    CWI Amsterdam, The Netherlands
     Erik Welch,        Anaconda, NVIDIA
-    Carl Yang,         University of Californie at Davis, Waymo
+    Carl Yang,         University of California at Davis, Waymo
     Yongzhe Zhang,     SOKENDAI, Japan
 
diff --git a/Makefile b/Makefile
index 7d22a3dcbc..2f91ff5fc4 100644
--- a/Makefile
+++ b/Makefile
@@ -51,30 +51,44 @@ JOBS ?= 8
 default: library
 
 library:
-	( cd build && cmake $(CMAKE_OPTIONS) .. && $(MAKE) --jobs=${JOBS} )
+	( cd build && cmake $(CMAKE_OPTIONS) .. && cmake --build . --config Release -j${JOBS} )
+
+# install only in SuiteSparse/lib and SuiteSparse/include
+local:
+	( cd build && cmake $(CMAKE_OPTIONS) -USUITESPARSE_PKGFILEDIR -DSUITESPARSE_LOCAL_INSTALL=1 .. && cmake --build . --config Release -j${JOBS} )
+
+# install CMAKE_INSTALL_PREFIX
+global:
+	( cd build && cmake $(CMAKE_OPTIONS) -USUITESPARSE_PKGFILEDIR -DSUITESPARSE_LOCAL_INSTALL=0 .. && cmake --build . --config Release -j${JOBS} )
 
 vanilla:
-	( cd build && cmake $(CMAKE_OPTIONS) -DLAGRAPH_VANILLA=1 .. && $(MAKE) --jobs=${JOBS} )
+	( cd build && cmake $(CMAKE_OPTIONS) -USUITESPARSE_PKGFILEDIR -DLAGRAPH_VANILLA=1 .. && cmake --build . --config Release -j${JOBS} )
 
 # compile with -g for debugging
 debug:
-	( cd build && cmake $(CMAKE_OPTIONS) -DCMAKE_BUILD_TYPE=Debug .. && $(MAKE) --jobs=${JOBS} )
+	( cd build && cmake $(CMAKE_OPTIONS) -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . --config Release -j${JOBS} )
 
 all: library
 
 test: library
-	( cd build && make test )
+	( cd build && ctest . || ctest . --rerun-failed --output-on-failure )
+
+verbose_test: library
+	( cd build && ctest . --verbose || ctest . --rerun-failed --output-on-failure )
+
+# target used in CI
+demos: test
 
 # just compile after running cmake; do not run cmake again
 remake:
-	( cd build && $(MAKE) --jobs=${JOBS} )
+	( cd build && cmake --build . --config Release -j${JOBS} )
 
 # just run cmake to set things up
 setup:
 	( cd build ; cmake $(CMAKE_OPTIONS) .. )
 
 install:
-	( cd build ; $(MAKE) install )
+	( cd build ; cmake --install . )
 
 # remove any installed libraries and #include files
 uninstall:
@@ -82,7 +96,7 @@ uninstall:
 
 # clean, compile, and run test coverage
 cov: distclean
-	( cd build && cmake -DCOVERAGE=1 .. && $(MAKE) --jobs=${JOBS} && make test_coverage ) 
+	( cd build && cmake -DCOVERAGE=1 .. && cmake --build . --config Release -j${JOBS} && cmake --build . --target test_coverage )
 
 # remove all files not in the distribution
 clean: distclean
diff --git a/cmake_modules/CodeCoverage.cmake b/cmake_modules/CodeCoverage.cmake
index a0ebde1173..2d5fcfb448 100644
--- a/cmake_modules/CodeCoverage.cmake
+++ b/cmake_modules/CodeCoverage.cmake
@@ -134,7 +134,7 @@ find_program( GCOV_PATH gcov )
 find_program( LCOV_PATH  NAMES lcov lcov.bat lcov.exe lcov.perl)
 find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
 find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
-find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
+find_program( GCOVR_PATH gcovr PATHS ${PROJECT_SOURCE_DIR}/scripts/test)
 find_program( CPPFILT_PATH NAMES c++filt )
 
 execute_process(
diff --git a/cmake_modules/FindGraphBLAS.cmake b/cmake_modules/FindGraphBLAS.cmake
index b6e7d19894..086eaf4351 100644
--- a/cmake_modules/FindGraphBLAS.cmake
+++ b/cmake_modules/FindGraphBLAS.cmake
@@ -9,13 +9,13 @@ SPDX-License-Identifier: BSD-2-Clause
 See additional acknowledgments in the LICENSE file,
 or contact permission@sei.cmu.edu for the full terms.
 
-Find the native GRAPHBLAS includes and library.
+Find the native GraphBLAS includes and library.
 
 IMPORTED Targets
 ^^^^^^^^^^^^^^^^
 
-This module defines :prop_tgt:`IMPORTED` target ``GRAPHBLAS::GRAPHBLAS``, if
-GRAPHBLAS has been found.
+This module defines :prop_tgt:`IMPORTED` target ``GraphBLAS::GraphBLAS``, if
+GraphBLAS has been found.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
@@ -35,75 +35,230 @@ This module defines the following variables:
 Hints
 ^^^^^
 
-A user may set ``GRAPHBLAS_ROOT`` or ``GraphBLAS_ROOT`` to a GraphBLAS
-installation root to tell this module where to look.
+A user may set ``GraphBLAS_ROOT`` to a GraphBLAS installation root to tell this
+module where to look (for cmake 3.27, you may also use ``GRAPHBLAS_ROOT``).
 
-Otherwise, the first place searched is in ../GraphBLAS, relative to the LAGraph
-source directory.  That is, if GraphBLAS and LAGraph reside in the same parent
-folder, side-by-side, and if it contains GraphBLAS/Include/GraphBLAS.h file and
-GraphBLAS/build/libgraphblas.so (or dylib, etc), then that version is used.
-This takes precedence over the system-wide installation of GraphBLAS, which
-might be an older version.  This method gives the user the ability to compile
-LAGraph with their own copy of GraphBLAS, ignoring the system-wide version.
+First, a GraphBLASConfig.cmake file is searched in the LAGraph/build or
+../GraphBLAS/build folder.  If that is not found, a search is made for
+GraphBLASConfig.cmake in the standard places that CMake looks.
+SuiteSparse::GraphBLAS v8.2.0 and following create a GraphBLASConfig.cmake
+file, and other GraphBLAS libraries may do the same.
 
-If SuiteSparse:GraphBLAS is the GraphBLAS library being utilized,
-all the Find*.cmake files in SuiteSparse are installed by 'make install' into
-/usr/local/lib/cmake/SuiteSparse (where '/usr/local' is the
-${CMAKE_INSTALL_PREFIX}).  To access this file, place the following commands
-in your CMakeLists.txt file.  See also SuiteSparse/Example/CMakeLists.txt:
+If the GraphBLASConfig.cmake file is not found, the GraphBLAS.h include file
+and compiled GraphBLAS library are searched for in the places given by
+GraphBLAS_ROOT, GRAPHBLAS_ROOT, LAGraph/.., LAGraph/../GraphBLAS, or
+LAGraph/../SuiteSparse/GraphBLAS.  This will find SuiteSparse:GraphBLAS
+versions 8.0.x and later, or it may find another GraphBLAS library that does
+not provide a GraphBLASConfig.cmake file.
 
-    set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
-        ${CMAKE_INSTALL_PREFIX}/lib/cmake/SuiteSparse )
+If SuiteSparse:GraphBLAS is used, all the *Config.cmake files in SuiteSparse
+are installed by 'make install' into the default location when compiling
+SuiteSparse.  CMake should know where to find them.
+
+SuiteSparse:GraphBLAS also comes in many Linux distros, spack, brew, conda,
+etc. Try:
+
+    apt search libsuitesparse-dev
+    spack info suite-sparse
+    brew info suite-sparse
+    conda search -c conda-forge graphblas
+
+If GraphBLAS is not found, or if a different version is found than what was
+expected, you can enable the LAGRAPH_DUMP option to display the places where
+CMake looks.
 
 #]=======================================================================]
 
+option ( LAGRAPH_DUMP "ON: display list of places to search. OFF (default): no debug output" OFF )
+
 # NB: this is built around assumptions about one particular GraphBLAS
 # installation (SuiteSparse:GraphBLAS). As other installations become available
 # changes to this will likely be required.
 
+#-------------------------------------------------------------------------------
+# find GraphBLASConfig.make in ../GraphBLAS (typically inside SuiteSparse):
+#-------------------------------------------------------------------------------
+
+if ( LAGRAPH_DUMP AND NOT GraphBLAS_DIR )
+    message ( STATUS "(1) Looking for GraphBLASConfig.cmake in... :
+    CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}
+    PROJECT_SOURCE_DIR/../GraphBLAS/build: ${PROJECT_SOURCE_DIR}/../GraphBLAS/build" )
+endif ( )
+
+find_package ( GraphBLAS ${GraphBLAS_FIND_VERSION} CONFIG
+    PATHS ${CMAKE_BINARY_DIR} ${PROJECT_SOURCE_DIR}/../GraphBLAS/build
+    NO_DEFAULT_PATH )
+
+set ( _lagraph_gb_common_tree ON )
+
+#-------------------------------------------------------------------------------
+# if not yet found, look for GraphBLASConfig.cmake in the standard places
+#-------------------------------------------------------------------------------
+
+if ( LAGRAPH_DUMP AND NOT TARGET SuiteSparse::GraphBLAS )
+message ( STATUS "(2) Looking for GraphBLASConfig.cmake in these places (in order):
+    GraphBLAS_ROOT: ${GraphBLAS_ROOT}" )
+if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.27" )
+    message ( STATUS "
+    GRAPHBLAS_ROOT: ${GRAPHBLAS_ROOT}" )
+endif ( )
+    message ( STATUS "
+    ENV GraphBLAS_ROOT: $ENV{GraphBLAS_ROOT}" )
+if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.27" )
+    message ( STATUS "
+    ENV GRAPHBLAS_ROOT: $ENV{GRAPHBLAS_ROOT}" )
+endif ( )
+message ( STATUS "
+    CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}
+    CMAKE_FRAMEWORK_PATH: ${CMAKE_FRAMEWORK_PATH}
+    CMAKE_APPBUNDLE_PATH: ${CMAKE_APPBUNDLE_PATH}
+    ENV GraphBLAS_DIR: $ENV{GraphBLAS_DIR}
+    ENV CMAKE_PREFIX_PATH: $ENV{CMAKE_PREFIX_PATH}
+    ENV CMAKE_FRAMEWORK_PATH: $ENV{CMAKE_FRAMEWORK_PATH}
+    ENV CMAKE_APPBUNDLE_PATH: $ENV{CMAKE_APPBUNDLE_PATH}
+    ENV PATH: $ENV{PATH}
+    CMake user package registry: (see cmake documentation)
+    CMAKE_SYSTEM_PREFIX_PATH: ${CMAKE_SYSTEM_PREFIX_PATH}
+    CMAKE_SYSTEM_FRAMEWORK_PATH: ${CMAKE_SYSTEM_FRAMEWORK_PATH}
+    CMAKE_SYSTEM_APPBUNDLE_PATH: ${CMAKE_SYSTEM_APPBUNDLE_PATH}
+    CMake system package registry: (see cmake documentation)"
+    )
+endif ( )
+
+if ( NOT TARGET SuiteSparse::GraphBLAS )
+    find_package ( GraphBLAS ${GraphBLAS_FIND_VERSION} CONFIG )
+    set ( _lagraph_gb_common_tree OFF )
+endif ( )
+
+if ( GraphBLAS_FOUND )
+    if ( TARGET SuiteSparse::GraphBLAS )
+        # It's not possible to create an alias of an alias.
+        get_property ( _graphblas_aliased TARGET SuiteSparse::GraphBLAS
+            PROPERTY ALIASED_TARGET )
+        if ( GRAPHBLAS_VERSION LESS "8.3.0" AND _lagraph_gb_common_tree )
+            # workaround for incorrect INTERFACE_INCLUDE_DIRECTORIES of
+            # SuiteSparse:GraphBLAS 8.2.x before installation
+            # (did not have "/Include")
+            get_property ( _inc TARGET SuiteSparse::GraphBLAS PROPERTY
+                INTERFACE_INCLUDE_DIRECTORIES )
+            if ( IS_DIRECTORY ${_inc}/Include )
+                if ( "${_graphblas_aliased}" STREQUAL "" )
+                    target_include_directories ( SuiteSparse::GraphBLAS INTERFACE
+                        ${_inc}/Include )
+                else ( )
+                    target_include_directories ( ${_graphblas_aliased} INTERFACE
+                        ${_inc}/Include )
+                endif ( )
+                message ( STATUS "additional include: ${_inc}/Include" )
+            endif ( )
+        endif ( )
+        if ( "${_graphblas_aliased}" STREQUAL "" )
+            add_library ( GraphBLAS::GraphBLAS ALIAS SuiteSparse::GraphBLAS )
+        else ( )
+            add_library ( GraphBLAS::GraphBLAS ALIAS ${_graphblas_aliased} )
+        endif ( )
+    endif ( )
+    if ( TARGET SuiteSparse::GraphBLAS_static )
+        # It's not possible to create an alias of an alias.
+        get_property ( _graphblas_aliased TARGET SuiteSparse::GraphBLAS_static
+            PROPERTY ALIASED_TARGET )
+        if ( GRAPHBLAS_VERSION LESS "8.3.0" AND _lagraph_gb_common_tree )
+            # workaround for incorrect INTERFACE_INCLUDE_DIRECTORIES of
+            # SuiteSparse:GraphBLAS 8.2.x before installation
+            # (did not have "/Include")
+            get_property ( _inc TARGET SuiteSparse::GraphBLAS_static PROPERTY
+                INTERFACE_INCLUDE_DIRECTORIES )
+            if ( IS_DIRECTORY ${_inc}/Include )
+                if ( "${_graphblas_aliased}" STREQUAL "" )
+                    target_include_directories ( SuiteSparse::GraphBLAS_static INTERFACE
+                        ${_inc}/Include )
+                else ( )
+                    target_include_directories ( ${_graphblas_aliased} INTERFACE
+                        ${_inc}/Include )
+                endif ( )
+                message ( STATUS "additional include: ${_inc}/Include" )
+            endif ( )
+        endif ( )
+        if ( "${_graphblas_aliased}" STREQUAL "" )
+            add_library ( GraphBLAS::GraphBLAS_static ALIAS SuiteSparse::GraphBLAS_static )
+        else ( )
+            add_library ( GraphBLAS::GraphBLAS_static ALIAS ${_graphblas_aliased} )
+        endif ( )
+    endif ( )
+    return ( )
+endif ( )
+
+#-------------------------------------------------------------------------------
+# if still not found, look for GraphBLAS.h and compiled libraries directly
+#-------------------------------------------------------------------------------
+
+# Older versions of SuiteSparse GraphBLAS (8.0 or older) or GraphBLAS libraries
+# not from SuiteSparse.
+
+if ( LAGRAPH_DUMP )
+    message ( STATUS "Looking for vanilla GraphBLAS (or older SuiteSparse),
+    GraphBLAS.h and the compiled GraphBLAS library in:
+    GraphBLAS_ROOT: ${GraphBLAS_ROOT}
+    ENV GraphBLAS_ROOT $ENV{GraphBLAS_ROOT}
+    GRAPHBLAS_ROOT: ${GRAPHBLAS_ROOT}
+    ENV GRAPHBLAS_ROOT ENV${GRAPHBLAS_ROOT}
+    PROJECT_SOURCE_DIR/..: ${PROJECT_SOURCE_DIR}/..
+    PROJECT_SOURCE_DIR/../GraphBLAS: ${PROJECT_SOURCE_DIR}/../GraphBLAS
+    PROJECT_SOURCE_DIR/../SuiteSparse/GraphBLAS: ${PROJECT_SOURCE_DIR}/../SuiteSparse/GraphBLAS"
+    )
+endif ( )
+
 # "Include" for SuiteSparse:GraphBLAS
 find_path ( GRAPHBLAS_INCLUDE_DIR
   NAMES GraphBLAS.h
+  HINTS ${GraphBLAS_ROOT}
+  HINTS ENV GraphBLAS_ROOT
   HINTS ${GRAPHBLAS_ROOT}
   HINTS ENV GRAPHBLAS_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/..
-  HINTS ${CMAKE_SOURCE_DIR}/../GraphBLAS
-  HINTS ${CMAKE_SOURCE_DIR}/../SuiteSparse/GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/..
+  HINTS ${PROJECT_SOURCE_DIR}/../GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/../SuiteSparse/GraphBLAS
   PATH_SUFFIXES include Include
-  )
+  NO_DEFAULT_PATH )
 
 # dynamic SuiteSparse:GraphBLAS library
 find_library ( GRAPHBLAS_LIBRARY
   NAMES graphblas
+  HINTS ${GraphBLAS_ROOT}
+  HINTS ENV GraphBLAS_ROOT
   HINTS ${GRAPHBLAS_ROOT}
   HINTS ENV GRAPHBLAS_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/..
-  HINTS ${CMAKE_SOURCE_DIR}/../GraphBLAS
-  HINTS ${CMAKE_SOURCE_DIR}/../SuiteSparse/GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/..
+  HINTS ${PROJECT_SOURCE_DIR}/../GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/../SuiteSparse/GraphBLAS
   PATH_SUFFIXES lib build alternative
-  )
+  NO_DEFAULT_PATH )
 
 if ( MSVC )
-    set ( STATIC_SUFFIX .lib )
     set ( STATIC_NAME graphblas_static )
 else ( )
-    set ( STATIC_SUFFIX .a )
     set ( STATIC_NAME graphblas )
 endif ( )
 
 # static SuiteSparse:GraphBLAS library
 set ( save ${CMAKE_FIND_LIBRARY_SUFFIXES} )
-set ( CMAKE_FIND_LIBRARY_SUFFIXES ${STATIC_SUFFIX} ${CMAKE_FIND_LIBRARY_SUFFIXES} )
+set ( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} )
 find_library ( GRAPHBLAS_STATIC
   NAMES ${STATIC_NAME}
+  HINTS ${GraphBLAS_ROOT}
+  HINTS ENV GraphBLAS_ROOT
   HINTS ${GRAPHBLAS_ROOT}
   HINTS ENV GRAPHBLAS_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/..
-  HINTS ${CMAKE_SOURCE_DIR}/../GraphBLAS
-  HINTS ${CMAKE_SOURCE_DIR}/../SuiteSparse/GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/..
+  HINTS ${PROJECT_SOURCE_DIR}/../GraphBLAS
+  HINTS ${PROJECT_SOURCE_DIR}/../SuiteSparse/GraphBLAS
   PATH_SUFFIXES lib build alternative
-  )
+  NO_DEFAULT_PATH )
+
 set ( CMAKE_FIND_LIBRARY_SUFFIXES ${save} )
+if ( MINGW AND GRAPHBLAS_STATIC MATCHES ".*\.dll\.a" )
+    set ( GRAPHBLAS_STATIC "" )
+endif ( )
 
 # get version of the library from the dynamic library name
 get_filename_component ( GRAPHBLAS_LIBRARY  ${GRAPHBLAS_LIBRARY} REALPATH )
@@ -114,6 +269,23 @@ string (
     ${GRAPHBLAS_FILENAME}
   )
 
+if ( GRAPHBLAS_VERSION )
+    if ( ${GRAPHBLAS_VERSION} MATCHES "([0-9]+).[0-9]+.[0-9]+" )
+        set ( GraphBLAS_VERSION_MAJOR ${CMAKE_MATCH_1} )
+    endif ( )
+    if ( ${GRAPHBLAS_VERSION} MATCHES "[0-9]+.([0-9]+).[0-9]+" )
+        set ( GraphBLAS_VERSION_MINOR ${CMAKE_MATCH_1} )
+    endif ( )
+    if ( ${GRAPHBLAS_VERSION} MATCHES "[0-9]+.[0-9]+.([0-9]+)" )
+        set ( GraphBLAS_VERSION_PATCH ${CMAKE_MATCH_1} )
+    endif ( )
+    if ( LAGRAPH_DUMP )
+        message ( STATUS "major: ${GraphBLAS_VERSION_MAJOR}" )
+        message ( STATUS "minor: ${GraphBLAS_VERSION_MINOR}" )
+        message ( STATUS "patch: ${GraphBLAS_VERSION_PATCH}" )
+    endif ( )
+endif ( )
+
 # set ( GRAPHBLAS_VERSION "" )
 if ( EXISTS "${GRAPHBLAS_INCLUDE_DIR}" AND NOT GRAPHBLAS_VERSION )
     # if the version does not appear in the filename, read the include file
@@ -123,13 +295,15 @@ if ( EXISTS "${GRAPHBLAS_INCLUDE_DIR}" AND NOT GRAPHBLAS_VERSION )
         REGEX "define GxB_IMPLEMENTATION_MINOR" )
     file ( STRINGS ${GRAPHBLAS_INCLUDE_DIR}/GraphBLAS.h GRAPHBLAS_PATCH_STR
         REGEX "define GxB_IMPLEMENTATION_SUB" )
-    message ( STATUS "major: ${GRAPHBLAS_MAJOR_STR}" )
-    message ( STATUS "minor: ${GRAPHBLAS_MINOR_STR}" )
-    message ( STATUS "patch: ${GRAPHBLAS_PATCH_STR}" )
-    string ( REGEX MATCH "[0-9]+" GRAPHBLAS_MAJOR ${GRAPHBLAS_MAJOR_STR} )
-    string ( REGEX MATCH "[0-9]+" GRAPHBLAS_MINOR ${GRAPHBLAS_MINOR_STR} )
-    string ( REGEX MATCH "[0-9]+" GRAPHBLAS_PATCH ${GRAPHBLAS_PATCH_STR} )
-    set (GRAPHBLAS_VERSION "${GRAPHBLAS_MAJOR}.${GRAPHBLAS_MINOR}.${GRAPHBLAS_PATCH}")
+    if ( LAGRAPH_DUMP )
+        message ( STATUS "major: ${GRAPHBLAS_MAJOR_STR}" )
+        message ( STATUS "minor: ${GRAPHBLAS_MINOR_STR}" )
+        message ( STATUS "patch: ${GRAPHBLAS_PATCH_STR}" )
+    endif ( )
+    string ( REGEX MATCH "[0-9]+" GraphBLAS_VERSION_MAJOR ${GRAPHBLAS_MAJOR_STR} )
+    string ( REGEX MATCH "[0-9]+" GraphBLAS_VERSION_MINOR ${GRAPHBLAS_MINOR_STR} )
+    string ( REGEX MATCH "[0-9]+" GraphBLAS_VERSION_PATCH ${GRAPHBLAS_PATCH_STR} )
+    set (GRAPHBLAS_VERSION "${GraphBLAS_VERSION_MAJOR}.${GraphBLAS_VERSION_MINOR}.${GraphBLAS_VERSION_PATCH}")
 endif ( )
 
 set ( GRAPHBLAS_LIBRARIES ${GRAPHBLAS_LIBRARY} )
@@ -162,3 +336,72 @@ else ( )
     set ( GRAPHBLAS_STATIC "" )
 endif ( )
 
+# Create target from information found
+
+if ( GRAPHBLAS_LIBRARY )
+    message ( STATUS "Create target GraphBLAS::GraphBLAS" )
+    # Get library name from filename of library
+    # This might be something like:
+    #   /usr/lib/libgraphblas.so or /usr/lib/libgraphblas.a or graphblas64
+    # convert to library name that can be used with -l flags for pkg-config
+    set ( GRAPHBLAS_LIBRARY_TMP ${GRAPHBLAS_LIBRARY} )
+    string ( FIND ${GRAPHBLAS_LIBRARY} "." _pos REVERSE )
+    if ( ${_pos} EQUAL "-1" )
+        set ( _graphblas_library_name ${GRAPHBLAS_LIBRARY} )
+    else ( )
+      set ( _kinds "SHARED" "STATIC" )
+      if ( WIN32 )
+          list ( PREPEND _kinds "IMPORT" )
+      endif ( )
+      foreach ( _kind IN LISTS _kinds )
+          set ( _regex ".*\\/(lib)?([^\\.]*)(${CMAKE_${_kind}_LIBRARY_SUFFIX})" )
+          if ( ${GRAPHBLAS_LIBRARY} MATCHES ${_regex} )
+              string ( REGEX REPLACE ${_regex} "\\2" _libname ${GRAPHBLAS_LIBRARY} )
+              if ( NOT "${_libname}" STREQUAL "" )
+                  set ( _graphblas_library_name ${_libname} )
+                  break ()
+              endif ( )
+          endif ( )
+      endforeach ( )
+    endif ( )
+
+    add_library ( GraphBLAS::GraphBLAS UNKNOWN IMPORTED )
+    set_target_properties ( GraphBLAS::GraphBLAS PROPERTIES
+        IMPORTED_LOCATION "${GRAPHBLAS_LIBRARY}"
+        INTERFACE_INCLUDE_DIRECTORIES "${GRAPHBLAS_INCLUDE_DIR}"
+        OUTPUT_NAME ${_graphblas_library_name} )
+endif ( )
+
+if ( GRAPHBLAS_STATIC )
+    message ( STATUS "Create target GraphBLAS::GraphBLAS_static" )
+    # Get library name from filename of library
+    # This might be something like:
+    #   /usr/lib/libgraphblas.so or /usr/lib/libgraphblas.a or graphblas64
+    # convert to library name that can be used with -l flags for pkg-config
+    set ( GRAPHBLAS_LIBRARY_TMP ${GRAPHBLAS_STATIC} )
+    string ( FIND ${GRAPHBLAS_STATIC} "." _pos REVERSE )
+    if ( ${_pos} EQUAL "-1" )
+        set ( _graphblas_library_name ${GRAPHBLAS_STATIC} )
+    else ( )
+      set ( _kinds "SHARED" "STATIC" )
+      if ( WIN32 )
+          list ( PREPEND _kinds "IMPORT" )
+      endif ( )
+      foreach ( _kind IN LISTS _kinds )
+          set ( _regex ".*\\/(lib)?([^\\.]*)(${CMAKE_${_kind}_LIBRARY_SUFFIX})" )
+          if ( ${GRAPHBLAS_STATIC} MATCHES ${_regex} )
+              string ( REGEX REPLACE ${_regex} "\\2" _libname ${GRAPHBLAS_STATIC} )
+              if ( NOT "${_libname}" STREQUAL "" )
+                  set ( _graphblas_library_name ${_libname} )
+                  break ()
+              endif ( )
+          endif ( )
+      endforeach ( )
+    endif ( )
+
+    add_library ( GraphBLAS::GraphBLAS_static UNKNOWN IMPORTED )
+    set_target_properties ( GraphBLAS::GraphBLAS_static PROPERTIES
+        IMPORTED_LOCATION "${GRAPHBLAS_STATIC}"
+        INTERFACE_INCLUDE_DIRECTORIES "${GRAPHBLAS_INCLUDE_DIR}"
+        OUTPUT_NAME ${_graphblas_library_name} )
+endif ( )
diff --git a/cmake_modules/FindLAGraph.cmake b/cmake_modules/FindLAGraph.cmake
deleted file mode 100644
index b0ea8deada..0000000000
--- a/cmake_modules/FindLAGraph.cmake
+++ /dev/null
@@ -1,142 +0,0 @@
-#[=======================================================================[.rst:
-FindLAGraph
---------
-
-LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
-SPDX-License-Identifier: BSD-2-Clause
-See additional acknowledgments in the LICENSE file,
-or contact permission@sei.cmu.edu for the full terms.
-
-Find the native LAGRAPH includes and library.
-
-IMPORTED Targets
-^^^^^^^^^^^^^^^^
-
-This module defines :prop_tgt:`IMPORTED` target ``LAGRAPH::LAGRAPH``, if
-LAGRAPH has been found.
-
-Result Variables
-^^^^^^^^^^^^^^^^
-
-This module defines the following variables:
-
-::
-
-  LAGRAPH_INCLUDE_DIR    - where to find LAGraph.h, etc.
-  LAGRAPH_LIBRARY        - dynamic LAGraph library
-  LAGRAPH_STATIC         - static LAGraph library
-  LAGRAPH_LIBRARIES      - List of libraries when using LAGraph.
-  LAGRAPH_FOUND          - True if LAGraph found.
-
-::
-
-Hints
-^^^^^
-
-A user may set ``LAGRAPH_ROOT`` to a LAGraph installation root to tell this
-module where to look.
-
-Otherwise, the first place searched is in ../LAGraph, relative to the current
-source directory.  That is, if the user application and LAGraph reside in the
-same parent folder, side-by-side, and if it contains LAGraph/include/LAGraph.h
-file and LAGraph/build/lib/liblagraph.so (or dylib, etc), then that version is
-used.  This takes precedence over the system-wide installation of LAGraph,
-which might be an older version.  This method gives the user the ability to
-compile LAGraph with their own copy of LAGraph, ignoring the system-wide
-version.
-
-#]=======================================================================]
-
-# "include" for LAGraph
-find_path(
-  LAGRAPH_INCLUDE_DIR
-  NAMES LAGraph.h
-  HINTS ${LAGRAPH_ROOT}
-  HINTS ENV LAGRAPH_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/../LAGraph
-  PATH_SUFFIXES include Include
-  )
-
-# dynamic LAGraph library
-find_library(
-  LAGRAPH_LIBRARY
-  NAMES lagraph
-  HINTS ${LAGRAPH_ROOT}
-  HINTS ENV LAGRAPH_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/../LAGraph
-  PATH_SUFFIXES lib build
-  )
-
-if ( MSVC )
-    set ( STATIC_SUFFIX .lib )
-else ( )
-    set ( STATIC_SUFFIX .a )
-endif ( )
-
-# static LAGraph library
-set ( save ${CMAKE_FIND_LIBRARY_SUFFIXES} )
-set ( CMAKE_FIND_LIBRARY_SUFFIXES ${STATIC_SUFFIX} ${CMAKE_FIND_LIBRARY_SUFFIXES} )
-find_library ( LAGRAPH_STATIC
-  NAMES lagraph
-  HINTS ${LAGRAPH_ROOT}
-  HINTS ENV LAGRAPH_ROOT
-  HINTS ${CMAKE_SOURCE_DIR}/../LAGraph
-  PATH_SUFFIXES lib build
-  )
-set ( CMAKE_FIND_LIBRARY_SUFFIXES ${save} )
-
-# get version of the library from the dynamic library name
-get_filename_component(LAGRAPH_LIBRARY ${LAGRAPH_LIBRARY} REALPATH)
-string(
-  REGEX MATCH "[0-9]+.[0-9]+.[0-9]+"
-  LAGRAPH_VERSION
-  ${LAGRAPH_LIBRARY}
-  )
-
-# set ( LAGRAPH_VERSION "" )
-if ( EXISTS "${LAGRAPH_INCLUDE_DIR}" AND NOT LAGRAPH_VERSION )
-    # if the version does not appear in the filename, read the include file
-    file ( STRINGS ${LAGRAPH_INCLUDE_DIR}/LAGraph.h LAGRAPH_MAJOR_STR
-        REGEX "define LAGRAPH_VERSION_MAJOR " )
-    file ( STRINGS ${LAGRAPH_INCLUDE_DIR}/LAGraph.h LAGRAPH_MINOR_STR
-        REGEX "define LAGRAPH_VERSION_MINOR " )
-    file ( STRINGS ${LAGRAPH_INCLUDE_DIR}/LAGraph.h LAGRAPH_PATCH_STR
-        REGEX "define LAGRAPH_VERSION_UPDATE " )
-    message ( STATUS "major: ${LAGRAPH_MAJOR_STR}" )
-    message ( STATUS "minor: ${LAGRAPH_MINOR_STR}" )
-    message ( STATUS "patch: ${LAGRAPH_PATCH_STR}" )
-    string ( REGEX MATCH "[0-9]+" LAGRAPH_MAJOR ${LAGRAPH_MAJOR_STR} )
-    string ( REGEX MATCH "[0-9]+" LAGRAPH_MINOR ${LAGRAPH_MINOR_STR} )
-    string ( REGEX MATCH "[0-9]+" LAGRAPH_PATCH ${LAGRAPH_PATCH_STR} )
-    set (LAGRAPH_VERSION "${LAGRAPH_MAJOR}.${LAGRAPH_MINOR}.${LAGRAPH_PATCH}")
-endif ( )
-
-set ( LAGRAPH_LIBRARIES ${LAGRAPH_LIBRARY} )
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(
-  LAGraph
-  REQUIRED_VARS LAGRAPH_LIBRARIES LAGRAPH_INCLUDE_DIR
-  VERSION_VAR LAGRAPH_VERSION
-  )
-
-mark_as_advanced(
-  LAGRAPH_INCLUDE_DIR
-  LAGRAPH_LIBRARY
-  LAGRAPH_STATIC
-  LAGRAPH_LIBRARIES
-  )
-
-if ( LAGRAPH_FOUND )
-    message ( STATUS "LAGraph version: " ${LAGRAPH_VERSION} )
-    message ( STATUS "LAGraph include: " ${LAGRAPH_INCLUDE_DIR} )
-    message ( STATUS "LAGraph library: " ${LAGRAPH_LIBRARY} )
-    message ( STATUS "LAGraph static:: " ${LAGRAPH_STATIC} )
-else ( )
-    message ( STATUS "LAGraph not found" )
-    set ( LAGRAPH_INCLUDE_DIR "" )
-    set ( LAGRAPH_LIBRARIES "" )
-    set ( LAGRAPH_LIBRARY "" )
-    set ( LAGRAPH_STATIC "" )
-endif ( )
-
diff --git a/cmake_modules/SuiteSparsePolicy.cmake b/cmake_modules/SuiteSparsePolicy.cmake
new file mode 100644
index 0000000000..f2d132aa74
--- /dev/null
+++ b/cmake_modules/SuiteSparsePolicy.cmake
@@ -0,0 +1,342 @@
+#-------------------------------------------------------------------------------
+# SuiteSparse/SuiteSparse_config/cmake_modules/SuiteSparsePolicy.cmake
+#-------------------------------------------------------------------------------
+
+# Copyright (c) 2022-2023, Timothy A. Davis.  All Rights Reserved.
+# SPDX-License-Identifier: BSD-3-clause
+
+#-------------------------------------------------------------------------------
+
+# SuiteSparse CMake policies.  The following parameters can be defined prior
+# to including this file:
+#
+#   CMAKE_BUILD_TYPE:   if not set, it is set below to "Release".
+#                       To use the "Debug" policy, precede this with
+#                       set ( CMAKE_BUILD_TYPE Debug )
+#
+#   SUITESPARSE_USE_CUDA: if OFF, CUDA is disabled.  if ON, CUDA is enabled,
+#                       if available.  Default: ON.
+#
+#   SUITESPARSE_LOCAL_INSTALL:      if true, "cmake --install" will install
+#                       into SuiteSparse/lib and SuiteSparse/include.
+#                       if false, "cmake --install" will install into the
+#                       default prefix (or the one configured with
+#                       CMAKE_INSTALL_PREFIX).  Requires cmake 3.19.
+#                       This is ignored when using the root CMakeLists.txt.
+#                       Set CMAKE_INSTALL_PREFIX instead.
+#                       Default: OFF
+#
+#   BUILD_SHARED_LIBS:  if true, shared libraries are built.
+#                       Default: ON.
+#
+#   BUILD_STATIC_LIBS:  if true, static libraries are built.
+#                       Default: ON, except for GraphBLAS, which
+#                       takes a long time to compile so the default for
+#                       GraphBLAS is false.
+#
+#   SUITESPARSE_CUDA_ARCHITECTURES:  a string, such as "all" or
+#                       "35;50;75;80" that lists the CUDA architectures to use
+#                       when compiling CUDA kernels with nvcc.  The "all"
+#                       option requires cmake 3.23 or later.
+#                       Default: "52;75;80".
+#
+#   BLA_VENDOR and BLA_SIZEOF_INTEGER: By default, SuiteSparse searches for
+#                       the BLAS library in a specific order.  If you wish to
+#                       use a specific BLAS library, set both of these with
+#                       (for example):
+#                       -DBLA_VENDOR=Intel10_64lp -DBLA_SIZEOF_INTEGER=4
+#                       Both settings must appear, or neither.
+#                       Default: neither are defined.
+#
+#   BLA_STATIC:         if ON, use static linkage for BLAS and LAPACK.
+#                       Default: not set (that is, the same as OFF)
+#
+#   SUITESPARSE_USE_64BIT_BLAS    if true, SuiteSparse will search for both
+#                       32-bit and 64-bit BLAS.  If false, only 32-bit BLAS
+#                       will be searched for.  Ignored if BLA_VENDOR and
+#                       BLA_SIZEOF_INTEGER are defined.
+#
+#   SUITESPARSE_C_TO_FORTRAN:  a string that defines how C calls Fortran.
+#                       Defaults to "(name,NAME) name" for Windows (lower case,
+#                       no underscore appended to the name), which is the
+#                       system that is most likely not to have a Fortran
+#                       compiler.  Defaults to "(name,NAME) name##_" otherwise.
+#                       This setting is only used if no Fortran compiler is
+#                       found.
+#
+#   SUITESPARSE_USE_FORTRAN:  if OFF, no Fortan files are compiled, and the
+#                       Fortran language is not enabled in any cmake scripts.
+#                       The built-in cmake script FortranCInterface is skipped.
+#                       This will require SUITESPARSE_C_TO_FORTRAN to be
+#                       defined explicitly, if the defaults are not appropriate
+#                       for your system.
+#                       Default: ON
+#
+#   SUITESPARSE_PKGFILEDIR: Directory where CMake Config and pkg-config files
+#                       will be installed.  By default, CMake Config files will
+#                       be installed in the subfolder `cmake` of the directory
+#                       where the (static) libraries will be installed (e.g.,
+#                       `lib`).  The `.pc` files for pkg-config will be
+#                       installed in the subfolder `pkgconfig` of the directory
+#                       where the (static) libraries will be installed.
+#                       Default: CMAKE_INSTALL_PREFIX, or SuiteSparse/lib if
+#                       SUITESPARSE_LOCAL_INSTALL is enabled.
+#
+#   SUITESPARSE_INCLUDEDIR_POSTFIX : Postfix for installation target of
+#                       header from SuiteSparse. Default: suitesparse, so the
+#                       default include directory is:
+#                       CMAKE_INSTALL_PREFIX/include/suitesparse
+#
+#   SUITESPARSE_USE_STRICT: SuiteSparse has many user-definable settings of the
+#                       form SUITESPARSE_USE_* or (package)_USE_* for some
+#                       particular package.  In general, these settings are not
+#                       strict.  For example, if SUITESPARSE_USE_OPENMP is
+#                       ON then OpenMP is preferred, but SuiteSparse can be
+#                       used without OpenMP so no error is generated if OpenMP
+#                       is not found.  However, if SUITESPARSE_USE_STRICT is
+#                       ON then all *_USE_* settings are treated strictly
+#                       and an error occurs if any are set to ON but the
+#                       corresponding package or setting is not available.  The
+#                       *_USE_SYSTEM_* settings are always treated as strict.
+#                       Default: OFF.
+
+message ( STATUS "Source:           ${CMAKE_SOURCE_DIR} ")
+message ( STATUS "Build:            ${CMAKE_BINARY_DIR} ")
+
+if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18.0" )
+    cmake_policy ( SET CMP0104 NEW )    # initialize CUDA architectures
+endif ( )
+
+if ( WIN32 )
+    set ( CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS true )
+    add_compile_definitions ( _CRT_SECURE_NO_WARNINGS )
+endif ( )
+
+enable_language ( C )
+include ( GNUInstallDirs )
+
+# add the cmake_modules folder for this package to the module path
+set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    ${CMAKE_SOURCE_DIR}/cmake_modules )
+
+# Use OpenMP
+option ( SUITESPARSE_USE_OPENMP "ON (default): Use OpenMP if available.  OFF: Do not use OpenMP" ON )
+
+# strict usage
+option ( SUITESPARSE_USE_STRICT "ON: treat all _USE__ settings as strict if they are ON. OFF (default): consider *_USE_* as preferences, not strict" OFF )
+
+# build the demos
+option ( SUITESPARSE_DEMOS "ON: Build the demo programs.  OFF (default): do not build the demo programs." OFF )
+
+# BUILD_SHARED_LIBS and BUILD_STATIC_LIBS options
+option ( BUILD_SHARED_LIBS "OFF: do not build shared libraries.  ON (default): build shared libraries" ON )
+
+if ( BUILD_STATIC_LIBS_DEFAULT_OFF )
+    option ( BUILD_STATIC_LIBS "OFF (default): do not build static libraries.  ON: build static libraries" OFF )
+else ( )
+    # For backwards compatibility, use NSTATIC if it is set.
+    if ( NSTATIC )
+        option ( BUILD_STATIC_LIBS "OFF: do not build static libraries.  ON (default): build static libraries" OFF )
+    else ( )
+        option ( BUILD_STATIC_LIBS "OFF: do not build static libraries.  ON (default): build static libraries" ON )
+    endif ( )
+endif ( )
+
+if ( NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS )
+    message ( FATAL_ERROR "At least one of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be set to ON." )
+endif ( )
+
+# installation options
+if ( NOT SUITESPARSE_ROOT_CMAKELISTS AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.19.0" )
+    # the SUITESPARSE_LOCAL_INSTALL option requires cmake 3.19.0 or later
+    option ( SUITESPARSE_LOCAL_INSTALL "Install in SuiteSparse/lib" OFF )
+else ( )
+    set ( SUITESPARSE_LOCAL_INSTALL OFF )
+endif ( )
+
+if ( SUITESPARSE_SECOND_LEVEL )
+    # some packages in SuiteSparse are in SuiteSparse/Package/Package
+    set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+        ${CMAKE_SOURCE_DIR}/../../lib/cmake )
+else ( )
+    # most packages in SuiteSparse are located in SuiteSparse/Package
+    set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+        ${CMAKE_SOURCE_DIR}/../lib/cmake )
+endif ( )
+
+# allow libraries to "see" each other if they are installed in a non-default LIBRARY_PATH
+list ( FIND CMAKE_INSTALL_RPATH "$ORIGIN" _idx )
+if ( _idx LESS 0 )
+    # "$ORIGIN" not yet included in CMAKE_INSTALL_RPATH
+    list ( PREPEND CMAKE_INSTALL_RPATH "$ORIGIN" )
+endif ( )
+
+set ( INSIDE_SUITESPARSE OFF )
+if ( NOT SUITESPARSE_ROOT_CMAKELISTS )
+    # determine if this Package is inside the SuiteSparse folder
+    if ( SUITESPARSE_LOCAL_INSTALL )
+        # if you do not want to install local copies of SuiteSparse
+        # packages in SuiteSparse/lib and SuiteSparse/, set
+        # SUITESPARSE_LOCAL_INSTALL to false in your CMake options.
+        if ( SUITESPARSE_SECOND_LEVEL )
+            # the package is normally located at the 2nd level inside SuiteSparse
+            # (SuiteSparse/GraphBLAS/GraphBLAS/ for example)
+            if ( EXISTS ${CMAKE_SOURCE_DIR}/../../SuiteSparse_config )
+                set ( INSIDE_SUITESPARSE true )
+            endif ( )
+        else ( )
+            # typical case, the package is at the 1st level inside SuiteSparse
+            # (SuiteSparse/AMD for example)
+            if ( EXISTS ${CMAKE_SOURCE_DIR}/../SuiteSparse_config )
+                set ( INSIDE_SUITESPARSE true )
+            endif ( )
+        endif ( )
+
+        if ( NOT INSIDE_SUITESPARSE )
+            message ( FATAL_ERROR "Unsupported layout for local installation. Correct the directory layout or unset SUITESPARSE_LOCAL_INSTALL." )
+        endif ( )
+
+    endif ( )
+endif ( )
+
+set ( SUITESPARSE_INCLUDEDIR_POSTFIX "suitesparse" CACHE STRING
+    "Postfix for installation target of header from SuiteSparse (default: \"suitesparse\")" )
+
+if ( SUITESPARSE_LOCAL_INSTALL )
+    if ( INSIDE_SUITESPARSE )
+        # ../lib and ../include exist: the package is inside SuiteSparse.
+        # find ( REAL_PATH ...) requires cmake 3.19.
+        if ( SUITESPARSE_SECOND_LEVEL )
+            file ( REAL_PATH  ${CMAKE_SOURCE_DIR}/../..
+                SUITESPARSE_LOCAL_PREFIX )
+        else ( )
+            file ( REAL_PATH  ${CMAKE_SOURCE_DIR}/..
+                SUITESPARSE_LOCAL_PREFIX )
+        endif ( )
+    endif ( )
+    set ( SUITESPARSE_LIBDIR ${SUITESPARSE_LOCAL_PREFIX}/lib )
+    set ( SUITESPARSE_INCLUDEDIR ${SUITESPARSE_LOCAL_PREFIX}/include/${SUITESPARSE_INCLUDEDIR_POSTFIX} )
+    set ( SUITESPARSE_BINDIR ${SUITESPARSE_LOCAL_PREFIX}/bin )
+else ( )
+    set ( SUITESPARSE_LIBDIR ${CMAKE_INSTALL_LIBDIR} )
+    set ( SUITESPARSE_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/${SUITESPARSE_INCLUDEDIR_POSTFIX} )
+    set ( SUITESPARSE_BINDIR ${CMAKE_INSTALL_BINDIR} )
+endif ( )
+
+if ( INSIDE_SUITESPARSE )
+    # append ../lib to the install and build runpaths
+    list ( APPEND CMAKE_INSTALL_RPATH ${SUITESPARSE_LIBDIR} )
+    list ( APPEND CMAKE_BUILD_RPATH ${SUITESPARSE_LIBDIR} )
+endif ( )
+
+set ( SUITESPARSE_PKGFILEDIR ${SUITESPARSE_LIBDIR} CACHE STRING
+    "Directory where CMake Config and pkg-config files will be installed" )
+
+message ( STATUS "Install lib:      ${SUITESPARSE_LIBDIR}" )
+message ( STATUS "Install include:  ${SUITESPARSE_INCLUDEDIR}" )
+message ( STATUS "Install bin:      ${SUITESPARSE_BINDIR}" )
+message ( STATUS "Install pkg-file: ${SUITESPARSE_PKGFILEDIR}" )
+message ( STATUS "Install rpath:    ${CMAKE_INSTALL_RPATH}" )
+message ( STATUS "Build   rpath:    ${CMAKE_BUILD_RPATH}" )
+
+if ( NOT CMAKE_BUILD_TYPE )
+    set ( CMAKE_BUILD_TYPE Release )
+endif ( )
+
+message ( STATUS "Build type:       ${CMAKE_BUILD_TYPE} ")
+
+set ( CMAKE_INCLUDE_CURRENT_DIR ON )
+
+#-------------------------------------------------------------------------------
+# check if Fortran is available and enabled
+#-------------------------------------------------------------------------------
+
+include ( CheckLanguage )
+option ( SUITESPARSE_USE_FORTRAN "ON (default): use Fortran. OFF: do not use Fortran" ON )
+if ( SUITESPARSE_USE_FORTRAN )
+    check_language ( Fortran )
+    if ( CMAKE_Fortran_COMPILER )
+        enable_language ( Fortran )
+        message ( STATUS "Fortran:          ${CMAKE_Fortran_COMPILER}" )
+        set ( SUITESPARSE_HAS_FORTRAN ON )
+    else ( )
+        # Fortran not available:
+        set ( SUITESPARSE_HAS_FORTRAN OFF )
+        message ( STATUS "Fortran:          not available" )
+    endif ( )
+else ( )
+    message ( STATUS "Fortran:          not enabled" )
+    set ( SUITESPARSE_HAS_FORTRAN OFF )
+endif ( )
+
+# check for strict usage
+if ( SUITESPARSE_USE_STRICT AND SUITESPARSE_USE_FORTRAN AND NOT SUITESPARSE_HAS_FORTRAN )
+    message ( FATAL_ERROR "Fortran required for SuiteSparse but not found" )
+endif ( )
+
+# default C-to-Fortran name mangling if Fortran compiler not found
+if ( MSVC )
+    # MS Visual Studio Fortran compiler does not mangle the Fortran name
+    set ( SUITESPARSE_C_TO_FORTRAN "(name,NAME) name"
+        CACHE STRING "C to Fortan name mangling" )
+else ( )
+    # Other systems (Linux, Mac) typically append an underscore
+    set ( SUITESPARSE_C_TO_FORTRAN "(name,NAME) name##_"
+        CACHE STRING "C to Fortan name mangling" )
+endif ( )
+
+#-------------------------------------------------------------------------------
+# find CUDA
+#-------------------------------------------------------------------------------
+
+option ( SUITESPARSE_USE_CUDA "ON (default): enable CUDA acceleration for SuiteSparse, OFF: do not use CUDA" ON )
+
+if ( SUITESPARSE_USE_CUDA )
+
+    # try finding CUDA
+    check_language ( CUDA )
+    # message ( STATUS "Looking for CUDA" )
+    if ( CMAKE_CUDA_COMPILER )
+        # with CUDA:
+        # message ( STATUS "Find CUDA tool kit:" )
+        # FindCUDAToolKit needs to have C or CXX enabled first (see above)
+        find_package ( CUDAToolkit )
+        message ( STATUS "CUDA toolkit :    " ${CUDAToolkit_FOUND} )
+        message ( STATUS "CUDA toolkit ver: " ${CUDAToolkit_VERSION} )
+        message ( STATUS "CUDA toolkit inc: " ${CUDAToolkit_INCLUDE_DIRS} )
+        message ( STATUS "CUDA toolkit lib: " ${CUDAToolkit_LIBRARY_DIR} )
+        if ( CUDAToolkit_VERSION VERSION_LESS "11.2" )
+            # CUDA is present but too old
+            message ( STATUS "CUDA:               not enabled (CUDA 11.2 or later required)" )
+            set ( SUITESPARSE_HAS_CUDA OFF )
+        else ( )
+            # CUDA 11.2 or later present
+            enable_language ( CUDA )
+            set ( SUITESPARSE_HAS_CUDA ON )
+        endif ( )
+    else ( )
+        # without CUDA:
+        message ( STATUS "CUDA:             not found" )
+        set ( SUITESPARSE_HAS_CUDA OFF )
+    endif ( )
+
+else ( )
+
+    # CUDA is disabled
+    set ( SUITESPARSE_HAS_CUDA OFF )
+
+endif ( )
+
+if ( SUITESPARSE_HAS_CUDA )
+    message ( STATUS "CUDA:             enabled" )
+    set ( SUITESPARSE_CUDA_ARCHITECTURES "52;75;80" CACHE STRING "CUDA architectures" )
+    set ( CMAKE_CUDA_ARCHITECTURES ${SUITESPARSE_CUDA_ARCHITECTURES} )
+else ( )
+    message ( STATUS "CUDA:             not enabled" )
+endif ( )
+
+# check for strict usage
+if ( SUITESPARSE_USE_STRICT AND SUITESPARSE_USE_CUDA AND NOT SUITESPARSE_HAS_CUDA )
+    message ( FATAL_ERROR "CUDA required for SuiteSparse but not found" )
+endif ( )
+
diff --git a/config/LAGraph.h.in b/config/LAGraph.h.in
index d49f1115eb..2fb2eef1df 100644
--- a/config/LAGraph.h.in
+++ b/config/LAGraph.h.in
@@ -2,7 +2,7 @@
 // LAGraph.h: user-visible include file for LAGraph
 //------------------------------------------------------------------------------
 
-// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 //
 // For additional details (including references to third party source code and
@@ -66,17 +66,17 @@
     #error "The GraphBLAS library must support the v2.0 C API Specification"
 #endif
 
-#if ( _MSC_VER && !__INTEL_COMPILER )
+#if ( _MSC_VER && !__INTEL_COMPILER && LG_DLL )
     #ifdef LG_LIBRARY
         // compiling LAGraph itself, exporting symbols to user apps
-        #define LAGRAPH_PUBLIC extern __declspec ( dllexport )
+        #define LAGRAPH_PUBLIC __declspec ( dllexport )
     #else
         // compiling the user application, importing symbols from LAGraph
-        #define LAGRAPH_PUBLIC extern __declspec ( dllimport )
+        #define LAGRAPH_PUBLIC __declspec ( dllimport )
     #endif
 #else
     // for other compilers
-    #define LAGRAPH_PUBLIC extern
+    #define LAGRAPH_PUBLIC
 #endif
 
 #if defined ( __cplusplus )
@@ -98,6 +98,9 @@
 
 #if ( !LAGRAPH_VANILLA ) && defined ( GxB_SUITESPARSE_GRAPHBLAS )
     // use SuiteSparse, and its GxB* extensions
+    #if GxB_IMPLEMENTATION < GxB_VERSION (7,1,0)
+    #error "If using SuiteSparse::GraphBLAS, version 7.1.0 or later is required"
+    #endif
     #define LAGRAPH_SUITESPARSE 1
 #else
     // use any GraphBLAS library (possibly SuiteSparse) but with no GxB*
@@ -367,6 +370,15 @@
     }                                           \
 }
 
+//==============================================================================
+// for C++ applications:
+//==============================================================================
+
+#if defined ( __cplusplus )
+extern "C"
+{
+#endif
+
 //==============================================================================
 // LAGraph memory management
 //==============================================================================
@@ -376,10 +388,10 @@
 // the following are pointers to the ANSI C11 malloc/calloc/realloc/free
 // functions.
 
-LAGRAPH_PUBLIC void * (* LAGraph_Malloc_function  ) (size_t)         ;
-LAGRAPH_PUBLIC void * (* LAGraph_Calloc_function  ) (size_t, size_t) ;
-LAGRAPH_PUBLIC void * (* LAGraph_Realloc_function ) (void *, size_t) ;
-LAGRAPH_PUBLIC void   (* LAGraph_Free_function    ) (void *)         ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Malloc_function  ) (size_t)         ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Calloc_function  ) (size_t, size_t) ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Realloc_function ) (void *, size_t) ;
+LAGRAPH_PUBLIC extern void   (* LAGraph_Free_function    ) (void *)         ;
 
 //------------------------------------------------------------------------------
 // LAGraph_Malloc:  allocate a block of memory (wrapper for malloc)
@@ -763,7 +775,7 @@ int LAGraph_Init
 // FUTURE: include these as built-in semirings in v2.1 C API, Table 3.9:
 
 // LAGraph semirings, created by LAGraph_Init or LAGr_Init:
-LAGRAPH_PUBLIC GrB_Semiring
+LAGRAPH_PUBLIC extern GrB_Semiring
 
     // LAGraph_plus_first_T: using the GrB_PLUS_MONOID_T monoid and the
     // corresponding GrB_FIRST_T multiplicative operator.
@@ -2503,4 +2515,8 @@ int LAGr_TriangleCount
     char *msg
 ) ;
 
+#if defined ( __cplusplus )
+}
+#endif
+
 #endif
diff --git a/config/LAGraph.pc.in b/config/LAGraph.pc.in
new file mode 100644
index 0000000000..4ca18e2544
--- /dev/null
+++ b/config/LAGraph.pc.in
@@ -0,0 +1,17 @@
+# LAGraph, Copyright (c) 2019-2023, LAGraph Contributors. All Rights Reserved.
+# SPDX-License-Identifier: BSD-2-Clause
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: LAGraph
+URL: https://github.com/GraphBLAS/LAGraph
+Description: Library plus test harness for collecting algorithms that use GraphBLAS
+Version: @LAGraph_VERSION_MAJOR@.@LAGraph_VERSION_MINOR@.@LAGraph_VERSION_SUB@
+Requires.private: GraphBLAS
+Libs: -L${libdir} -l@SUITESPARSE_LIB_BASE_NAME@
+Libs.private: @LAGRAPH_STATIC_LIBS@
+Cflags: -I${includedir} -DLG_DLL
+Cflags.private: -ULG_DLL
diff --git a/config/LAGraphConfig.cmake.in b/config/LAGraphConfig.cmake.in
new file mode 100644
index 0000000000..96ae114d08
--- /dev/null
+++ b/config/LAGraphConfig.cmake.in
@@ -0,0 +1,185 @@
+#-------------------------------------------------------------------------------
+# SuiteSparse/LAGraph/cmake_modules/LAGraphConfig.cmake
+#-------------------------------------------------------------------------------
+
+# The following copyright and license applies to just this file only, not to
+# the library itself:
+# LAGraphConfig.cmake, Copyright (c) 2019-2023, LAGraph Contributors. All
+# Rights Reserved.
+# SPDX-License-Identifier: BSD-3-clause
+
+#-------------------------------------------------------------------------------
+
+# Finds the LAGraph include file and compiled library.
+# The following targets are defined:
+#   SuiteSparse::LAGraph           - for the shared library (if available)
+#   SuiteSparse::LAGraph_static    - for the static library (if available)
+
+# For backward compatibility the following variables are set:
+
+# LAGRAPH_INCLUDE_DIR - where to find LAGraph.h, etc.
+# LAGRAPH_LIBRARY     - dynamic LAGraph library
+# LAGRAPH_STATIC      - static LAGraph library
+# LAGRAPH_LIBRARIES   - libraries when using LAGraph
+# LAGRAPH_FOUND       - true if LAGraph found
+
+# Set ``CMAKE_MODULE_PATH`` to the parent folder where this module file is
+# installed.
+
+#-------------------------------------------------------------------------------
+
+@PACKAGE_INIT@
+
+set ( LAGRAPH_DATE "@LAGraph_DATE@" )
+set ( LAGRAPH_VERSION_MAJOR @LAGraph_VERSION_MAJOR@ )
+set ( LAGRAPH_VERSION_MINOR @LAGraph_VERSION_MINOR@ )
+set ( LAGRAPH_VERSION_PATCH @LAGraph_VERSION_SUB@ )
+set ( LAGRAPH_VERSION "@LAGraph_VERSION_MAJOR@.@LAGraph_VERSION_MINOR@.@LAGraph_VERSION_SUB@" )
+
+# Check for dependent targets
+include ( CMakeFindDependencyMacro )
+set ( _dependencies_found ON )
+
+if ( NOT TARGET GraphBLAS::GraphBLAS )
+    # Look GraphBLAS 
+    list ( PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR} )
+    find_dependency ( GraphBLAS @GraphBLAS_VERSION_MAJOR@.@GraphBLAS_VERSION_MINOR@ )
+endif ( )
+
+if ( NOT GraphBLAS_FOUND )
+    set ( LAGraph_FOUND OFF )
+    return ( )
+endif ( )
+
+# Look for OpenMP
+if ( @LAGRAPH_HAS_OPENMP@ AND NOT OpenMP_C_FOUND )
+    find_dependency ( OpenMP )
+    if ( NOT OpenMP_C_FOUND )
+        set ( _dependencies_found OFF )
+    endif ( )
+endif ( )
+
+if ( NOT _dependencies_found )
+    set ( LAGraph_FOUND OFF )
+    return ( )
+endif ( )
+
+# Import target
+include ( ${CMAKE_CURRENT_LIST_DIR}/LAGraphTargets.cmake )
+
+if ( @LAGRAPH_HAS_OPENMP@ )
+    if ( TARGET SuiteSparse::LAGraph )
+        get_property ( _lagraph_aliased TARGET SuiteSparse::LAGraph
+            PROPERTY ALIASED_TARGET )
+        if ( "${_lagraph_aliased}" STREQUAL "" )
+            target_include_directories ( SuiteSparse::LAGraph SYSTEM AFTER INTERFACE
+                "$<TARGET_PROPERTY:OpenMP::OpenMP_C,INTERFACE_INCLUDE_DIRECTORIES>" )
+        else ( )
+            target_include_directories ( ${_lagraph_aliased} SYSTEM AFTER INTERFACE
+                "$<TARGET_PROPERTY:OpenMP::OpenMP_C,INTERFACE_INCLUDE_DIRECTORIES>" )
+        endif ( )
+    endif ( )
+    if ( TARGET SuiteSparse::LAGraph_static )
+        get_property ( _lagraph_aliased TARGET SuiteSparse::LAGraph_static
+            PROPERTY ALIASED_TARGET )
+        if ( "${_lagraph_aliased}" STREQUAL "" )
+            target_include_directories ( SuiteSparse::LAGraph_static SYSTEM AFTER INTERFACE
+                "$<TARGET_PROPERTY:OpenMP::OpenMP_C,INTERFACE_INCLUDE_DIRECTORIES>" )
+        else ( )
+            target_include_directories ( ${_lagraph_aliased} SYSTEM AFTER INTERFACE
+                "$<TARGET_PROPERTY:OpenMP::OpenMP_C,INTERFACE_INCLUDE_DIRECTORIES>" )
+        endif ( )
+    endif ( )
+endif ( )
+
+# The following is only for backward compatibility with FindLAGraph.
+
+set ( _target_shared SuiteSparse::LAGraph )
+set ( _target_static SuiteSparse::LAGraph_static )
+set ( _var_prefix "LAGRAPH" )
+
+if ( NOT @BUILD_SHARED_LIBS@ AND NOT TARGET ${_target_shared} )
+    # make sure there is always an import target without suffix )
+    add_library ( ${_target_shared} ALIAS ${_target_static} )
+endif ( )
+if ( NOT @BUILD_SHARED_LIBS@ AND NOT TARGET SuiteSparse::LAGraphX )
+    # make sure there is always an import target without suffix )
+    add_library ( SuiteSparse::LAGraphX ALIAS SuiteSparse::LAGraphX_static )
+endif ( )
+
+get_target_property ( ${_var_prefix}_INCLUDE_DIR ${_target_shared} INTERFACE_INCLUDE_DIRECTORIES )
+if ( ${_var_prefix}_INCLUDE_DIR )
+    # First item in SuiteSparse targets contains the "main" header directory.
+    list ( GET ${_var_prefix}_INCLUDE_DIR 0 ${_var_prefix}_INCLUDE_DIR )
+endif ( )
+get_target_property ( ${_var_prefix}_LIBRARY ${_target_shared} IMPORTED_IMPLIB )
+if ( NOT ${_var_prefix}_LIBRARY )
+    get_target_property ( _library_chk ${_target_shared} IMPORTED_LOCATION )
+    if ( EXISTS ${_library_chk} )
+        set ( ${_var_prefix}_LIBRARY ${_library_chk} )
+    endif ( )
+endif ( )
+if ( TARGET ${_target_static} )
+    get_target_property ( ${_var_prefix}_STATIC ${_target_static} IMPORTED_LOCATION )
+endif ( )
+
+# Check for most common build types
+set ( _config_types "Debug" "Release" "RelWithDebInfo" "MinSizeRel" "None" )
+
+get_property ( _isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG )
+if ( _isMultiConfig )
+    # For multi-configuration generators (e.g., Visual Studio), prefer those
+    # configurations.
+    list ( PREPEND _config_types ${CMAKE_CONFIGURATION_TYPES} )
+else ( )
+    # For single-configuration generators, prefer the current configuration.
+    list ( PREPEND _config_types ${CMAKE_BUILD_TYPE} )
+endif ( )
+
+list ( REMOVE_DUPLICATES _config_types )
+
+foreach ( _config ${_config_types} )
+    string ( TOUPPER ${_config} _uc_config )
+    if ( NOT ${_var_prefix}_LIBRARY )
+        get_target_property ( _library_chk ${_target_shared}
+            IMPORTED_IMPLIB_${_uc_config} )
+        if ( EXISTS ${_library_chk} )
+            set ( ${_var_prefix}_LIBRARY ${_library_chk} )
+        endif ( )
+    endif ( )
+    if ( NOT ${_var_prefix}_LIBRARY )
+        get_target_property ( _library_chk ${_target_shared}
+            IMPORTED_LOCATION_${_uc_config} )
+        if ( EXISTS ${_library_chk} )
+            set ( ${_var_prefix}_LIBRARY ${_library_chk} )
+        endif ( )
+    endif ( )
+    if ( TARGET ${_target_static} AND NOT ${_var_prefix}_STATIC )
+        get_target_property ( _library_chk ${_target_static}
+            IMPORTED_LOCATION_${_uc_config} )
+        if ( EXISTS ${_library_chk} )
+            set ( ${_var_prefix}_STATIC ${_library_chk} )
+        endif ( )
+    endif ( )
+endforeach ( )
+
+set ( LAGRAPH_LIBRARIES ${LAGRAPH_LIBRARY} )
+
+macro ( suitesparse_check_exist _var _files )
+  # ignore generator expressions
+  string ( GENEX_STRIP "${_files}" _files2 )
+
+  foreach ( _file ${_files2} )
+    if ( NOT EXISTS "${_file}" )
+      message ( FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist!" )
+    endif ( )
+  endforeach ()
+endmacro ( )
+
+suitesparse_check_exist ( LAGRAPH_INCLUDE_DIR ${LAGRAPH_INCLUDE_DIR} )
+suitesparse_check_exist ( LAGRAPH_LIBRARY ${LAGRAPH_LIBRARY} )
+
+message ( STATUS "LAGraph version: ${LAGRAPH_VERSION}" )
+message ( STATUS "LAGraph include: ${LAGRAPH_INCLUDE_DIR}" )
+message ( STATUS "LAGraph library: ${LAGRAPH_LIBRARY}" )
+message ( STATUS "LAGraph static:  ${LAGRAPH_STATIC}" )
diff --git a/experimental/CMakeLists.txt b/experimental/CMakeLists.txt
index a88386ffca..6038808bfc 100644
--- a/experimental/CMakeLists.txt
+++ b/experimental/CMakeLists.txt
@@ -2,7 +2,7 @@
 # LAGraph/experimental/CMakeLists.txt:  cmake script for LAGraph/experimental
 #-------------------------------------------------------------------------------
 
-# LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+# LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 # SPDX-License-Identifier: BSD-2-Clause
 #
 # For additional details (including references to third party source code and
@@ -13,9 +13,9 @@
 
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/include
-    ${CMAKE_SOURCE_DIR}/src/utility
-    ${CMAKE_SOURCE_DIR}/deps/json_h )
+include_directories (
+    ${PROJECT_SOURCE_DIR}/src/utility
+    ${PROJECT_SOURCE_DIR}/deps/json_h )
 
 file ( GLOB LAGRAPHX_LIB_SOURCES "utility/*.c" "algorithm/*.c" )
 
@@ -23,50 +23,82 @@ file ( GLOB LAGRAPHX_LIB_SOURCES "utility/*.c" "algorithm/*.c" )
 # dynamic lagraphx library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphx SHARED ${LAGRAPHX_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphx PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11
-    PUBLIC_HEADER "include/LAGraphX.h" )
-set_property ( TARGET lagraphx PROPERTY C_STANDARD 11 )
-target_link_libraries ( lagraphx PUBLIC lagraph ${GRAPHBLAS_LIBRARIES} )
-target_link_directories ( lagraphx BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+if ( BUILD_SHARED_LIBS )
+    add_library ( LAGraphX SHARED ${LAGRAPHX_LIB_SOURCES} )
+    set_target_properties ( LAGraphX PROPERTIES
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        OUTPUT_NAME lagraphx
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        PUBLIC_HEADER "include/LAGraphX.h"
+        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/dlls )
+
+    if ( ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.25" )
+        set_target_properties ( LAGraphX PROPERTIES EXPORT_NO_SYSTEM ON )
+    endif ( )
+
+    target_link_libraries ( LAGraphX PRIVATE LAGraph GraphBLAS::GraphBLAS )
+
+    target_include_directories ( LAGraphX PUBLIC
+        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+        $<INSTALL_INTERFACE:${SUITESPARSE_INCLUDEDIR}> )
+
+    target_compile_definitions ( LAGraphX PRIVATE LGX_LIBRARY )
+    target_compile_definitions ( LAGraphX PUBLIC LGX_DLL )
+endif ( )
 
 #-------------------------------------------------------------------------------
 # static lagraphx library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphx_static STATIC ${LAGRAPHX_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphx_static PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    OUTPUT_NAME lagraphx
-    POSITION_INDEPENDENT_CODE OFF
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-
-if ( MSVC )
-    set_target_properties ( lagraphx_static PROPERTIES
-        OUTPUT_NAME lagraphx_static )
-endif ( )
+if ( BUILD_STATIC_LIBS )
+    add_library ( LAGraphX_static STATIC ${LAGRAPHX_LIB_SOURCES} )
+    set_target_properties ( LAGraphX_static PROPERTIES
+        OUTPUT_NAME lagraphx
+        POSITION_INDEPENDENT_CODE OFF
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        PUBLIC_HEADER "include/LAGraphX.h" )
 
-set_property ( TARGET lagraphx_static PROPERTY C_STANDARD 11 )
-target_link_libraries ( lagraphx_static PUBLIC lagraph_static ${GRAPHBLAS_LIBRARIES} )
-target_link_directories ( lagraphx_static BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+    if ( MSVC )
+        set_target_properties ( LAGraphX_static PROPERTIES
+            OUTPUT_NAME lagraphx_static )
+    endif ( )
+
+    if ( ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.25" )
+        set_target_properties ( LAGraphX_static PROPERTIES EXPORT_NO_SYSTEM ON )
+    endif ( )
+
+    if ( TARGET GraphBLAS::GraphBLAS_static )
+        target_link_libraries ( LAGraphX_static PRIVATE GraphBLAS::GraphBLAS_static )
+    else ( )
+        target_link_libraries ( LAGraphX_static PRIVATE GraphBLAS::GraphBLAS )
+    endif ( )
+
+    target_include_directories ( LAGraphX_static PUBLIC
+        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+        $<INSTALL_INTERFACE:${SUITESPARSE_INCLUDEDIR}> )
+endif ( )
 
 #-------------------------------------------------------------------------------
 # add OpenMP
 #-------------------------------------------------------------------------------
 
-if ( OPENMP_FOUND )
-    target_link_libraries ( lagraphx PUBLIC lagraph ${OpenMP_C_LIBRARIES} )
-    target_link_libraries ( lagraphx_static PUBLIC lagraph_static ${OpenMP_C_LIBRARIES} )
+if ( OpenMP_C_FOUND )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries ( LAGraphX PRIVATE OpenMP::OpenMP_C )
+    endif ( )
+    if ( BUILD_STATIC_LIBS )
+        target_link_libraries ( LAGraphX_static PRIVATE OpenMP::OpenMP_C )
+    endif ( )
 endif ( )
 
 #-------------------------------------------------------------------------------
 # applications
 #-------------------------------------------------------------------------------
 
-add_subdirectory ( test )
-add_subdirectory ( benchmark )
-
+if ( BUILD_TESTING )
+    add_subdirectory ( test )
+    add_subdirectory ( benchmark )
+endif ( )
diff --git a/experimental/algorithm/LAGraph_AllKCore.c b/experimental/algorithm/LAGraph_AllKCore.c
index b1bad837d2..6500687168 100644
--- a/experimental/algorithm/LAGraph_AllKCore.c
+++ b/experimental/algorithm/LAGraph_AllKCore.c
@@ -94,6 +94,7 @@ int LAGraph_KCore_All
 
     //change deg vector to int32 if needed
     if(int_type == GrB_INT32){
+        GrB_free (&deg) ;
         GRB_TRY (GrB_Vector_new(&deg, int_type, n)) ;
         GRB_TRY (GrB_assign (deg, G->out_degree, NULL, G->out_degree, GrB_ALL, n, NULL)) ;
     }
diff --git a/experimental/algorithm/LAGraph_BF_full.c b/experimental/algorithm/LAGraph_BF_full.c
index 3be0e48290..4d91d52a4b 100644
--- a/experimental/algorithm/LAGraph_BF_full.c
+++ b/experimental/algorithm/LAGraph_BF_full.c
@@ -218,8 +218,9 @@ GrB_Info LAGraph_BF_full
     LG_TRY (LAGraph_GetNumThreads (&nthreads_outer, &nthreads_inner, msg)) ;
     nthreads = nthreads_outer * nthreads_inner ;
     printf ("nthreads %d\n", nthreads) ;
+    int64_t k;
     #pragma omp parallel for num_threads(nthreads) schedule(static)
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         if (w[k] == 0)             //diagonal entries
         {
@@ -292,7 +293,7 @@ GrB_Info LAGraph_BF_full
     LAGRAPH_TRY (LAGraph_Malloc ((void **) &h , nz, sizeof(GrB_Index), msg)) ;
     LAGRAPH_TRY (LAGraph_Malloc ((void **) &pi, nz, sizeof(GrB_Index), msg)) ;
 
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         w [k] = W[k].w ;
         h [k] = W[k].h ;
diff --git a/experimental/algorithm/LAGraph_BF_full1.c b/experimental/algorithm/LAGraph_BF_full1.c
index f49b549ef7..5dab6d03cd 100644
--- a/experimental/algorithm/LAGraph_BF_full1.c
+++ b/experimental/algorithm/LAGraph_BF_full1.c
@@ -54,6 +54,7 @@
     GrB_free(&BF_LT_Tuple3);           \
     GrB_free(&BF_lMIN_Tuple3_Monoid);  \
     GrB_free(&BF_lMIN_PLUSrhs_Tuple3); \
+    GrB_free(&BF_Identity_Tuple3 );    \
     LAGraph_Free ((void**)&I, NULL);   \
     LAGraph_Free ((void**)&J, NULL);   \
     LAGraph_Free ((void**)&w, NULL);   \
@@ -173,15 +174,15 @@ GrB_Info LAGraph_BF_full1
     // tmp vector to store distance vector after n (i.e., V) loops
     GrB_Vector d = NULL, dmasked = NULL, dless = NULL;
     GrB_Matrix Atmp = NULL;
-    GrB_Type BF_Tuple3;
+    GrB_Type BF_Tuple3 = NULL ;
 
-    GrB_BinaryOp BF_lMIN_Tuple3;
-    GrB_BinaryOp BF_PLUSrhs_Tuple3;
-    GrB_UnaryOp BF_Identity_Tuple3;
-    GrB_BinaryOp BF_LT_Tuple3;
+    GrB_BinaryOp BF_lMIN_Tuple3 = NULL ;
+    GrB_BinaryOp BF_PLUSrhs_Tuple3 = NULL ;
+    GrB_UnaryOp BF_Identity_Tuple3 = NULL ;
+    GrB_BinaryOp BF_LT_Tuple3 = NULL ;
 
-    GrB_Monoid BF_lMIN_Tuple3_Monoid;
-    GrB_Semiring BF_lMIN_PLUSrhs_Tuple3;
+    GrB_Monoid BF_lMIN_Tuple3_Monoid = NULL ;
+    GrB_Semiring BF_lMIN_PLUSrhs_Tuple3 = NULL ;
 
     GrB_Index nrows, ncols, n, nz;  // n = # of row/col, nz = # of nnz in graph
     GrB_Index *I = NULL, *J = NULL; // for col/row indices of entries from A
@@ -248,8 +249,9 @@ GrB_Info LAGraph_BF_full1
     LG_TRY (LAGraph_GetNumThreads (&nthreads_outer, &nthreads_inner, msg)) ;
     nthreads = nthreads_outer * nthreads_inner ;
     printf ("nthreads %d\n", nthreads) ;
+    int64_t k;
     #pragma omp parallel for num_threads(nthreads) schedule(static)
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         W[k] = (BF1_Tuple3_struct) { .w = w[k], .h = 1, .pi = I[k] + 1 };
     }
@@ -350,7 +352,7 @@ GrB_Info LAGraph_BF_full1
 
     GRB_TRY (GrB_Vector_extractTuples_UDT (I, (void *) W, &n, d));
 
-    for (GrB_Index k = 0; k < n; k++)
+    for (k = 0; k < n; k++)
     {
         w [k] = W[k].w ;
         h [k] = W[k].h ;
diff --git a/experimental/algorithm/LAGraph_BF_full1a.c b/experimental/algorithm/LAGraph_BF_full1a.c
index e07c1ec0ce..28541da9e1 100644
--- a/experimental/algorithm/LAGraph_BF_full1a.c
+++ b/experimental/algorithm/LAGraph_BF_full1a.c
@@ -240,8 +240,9 @@ GrB_Info LAGraph_BF_full1a
     LG_TRY (LAGraph_GetNumThreads (&nthreads_outer, &nthreads_inner, msg)) ;
     nthreads = nthreads_outer * nthreads_inner ;
     printf ("nthreads %d\n", nthreads) ;
+    int64_t k;
     #pragma omp parallel for num_threads(nthreads) schedule(static)
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         W[k] = (BF_Tuple3_struct) { .w = w[k], .h = 1, .pi = I[k] + 1 };
     }
@@ -373,7 +374,7 @@ GrB_Info LAGraph_BF_full1a
 
     GRB_TRY (GrB_Vector_extractTuples_UDT (I, (void *) W, &n, d));
 
-    for (GrB_Index k = 0; k < n; k++)
+    for (k = 0; k < n; k++)
     {
         w [k] = W[k].w ;
         h [k] = W[k].h ;
diff --git a/experimental/algorithm/LAGraph_BF_full2.c b/experimental/algorithm/LAGraph_BF_full2.c
index 9ae239d707..47eaeabb67 100644
--- a/experimental/algorithm/LAGraph_BF_full2.c
+++ b/experimental/algorithm/LAGraph_BF_full2.c
@@ -238,8 +238,9 @@ GrB_Info LAGraph_BF_full2
     LG_TRY (LAGraph_GetNumThreads (&nthreads_outer, &nthreads_inner, msg)) ;
     nthreads = nthreads_outer * nthreads_inner ;
     printf ("nthreads %d\n", nthreads) ;
+    int64_t k;
     #pragma omp parallel for num_threads(nthreads) schedule(static)
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         if (w[k] == 0)             //diagonal entries
         {
@@ -331,7 +332,7 @@ GrB_Info LAGraph_BF_full2
     nz = n ;
     GRB_TRY (GrB_Vector_extractTuples_UDT (I, (void *) W, &nz, d));
 
-    for (GrB_Index k = 0; k < nz; k++)
+    for (k = 0; k < nz; k++)
     {
         w [k] = W[k].w ;
         h [k] = W[k].h ;
diff --git a/experimental/algorithm/LAGraph_BF_pure_c_double.c b/experimental/algorithm/LAGraph_BF_pure_c_double.c
index 1c99b5da06..bf514db5f8 100644
--- a/experimental/algorithm/LAGraph_BF_pure_c_double.c
+++ b/experimental/algorithm/LAGraph_BF_pure_c_double.c
@@ -44,6 +44,8 @@
     LAGraph_Free ((void**) &pi, NULL) ;     \
 }
 
+#include <float.h>
+
 #include "LG_internal.h"
 #include <LAGraphX.h>
 
@@ -122,7 +124,7 @@ GrB_Info LAGraph_BF_pure_c_double
         {
             i = I[k];
             j = J[k];
-            if (d[j] > d[i] + W[k])
+            if (d[j] > d[i] + W[k] + DBL_EPSILON*d[j])
             {
                 LG_FREE_ALL ;
                 return (GrB_NO_VALUE) ;
diff --git a/experimental/algorithm/LAGraph_FastGraphletTransform.c b/experimental/algorithm/LAGraph_FastGraphletTransform.c
index cbcc2acc1c..568974a08c 100644
--- a/experimental/algorithm/LAGraph_FastGraphletTransform.c
+++ b/experimental/algorithm/LAGraph_FastGraphletTransform.c
@@ -58,6 +58,20 @@
     GrB_free (&U_inv) ;             \
     GrB_free (&F_raw) ;             \
     GrB_free (&C_4) ;               \
+    GrB_free (&Sub_one_mult) ;      \
+    GrB_free (&T) ;                 \
+    if (A_Tiles != NULL)                                                \
+    {                                                                   \
+        for (int i = 0; i < tile_cnt; ++i) GrB_free (&A_Tiles [i]) ;    \
+    }                                                                   \
+    if (D_Tiles != NULL)                                                \
+    {                                                                   \
+        for (int i = 0; i < tile_cnt; ++i) GrB_free (&D_Tiles [i]) ;    \
+    }                                                                   \
+    if (C_Tiles != NULL)                                                \
+    {                                                                   \
+        for (int i = 0; i < tile_cnt; ++i) GrB_free (&C_Tiles [i]) ;    \
+    }                                                                   \
 }
 
 #define LG_FREE_ALL                 \
@@ -90,6 +104,13 @@ int LAGraph_FastGraphletTransform
     GrB_Index const U_inv_J[] = {0, 1, 2, 4, 3, 4, 4, 5, 9, 10, 12, 13, 14, 15, 6, 10, 11, 12, 13, 14, 15, 7, 9, 10, 13, 14, 15, 8, 11, 14, 15, 9, 13, 15, 10, 13, 14, 15, 11, 14, 15, 12, 13, 14, 15, 13, 15, 14, 15, 15} ;
     int64_t const U_inv_X[] = {1, 1, 1, -2, 1, -1, 1, 1, -2, -1, -2, 4, 2, -6, 1, -1, -2, -2, 2, 4, -6, 1, -1, -1, 2, 1, -3, 1, -1, 1, -1, 1, -2, 3, 1, -2, -2, 6, 1, -2, 3, 1, -1, -1, 3, 1, -3, 1, -3, 1} ;
     GrB_Index const U_inv_nvals = 50;
+    GrB_UnaryOp Sub_one_mult = NULL ;
+    int tile_cnt = 0 ;
+    GrB_Matrix *A_Tiles = NULL ;
+    GrB_Matrix *D_Tiles = NULL ;
+    GrB_Matrix *C_Tiles = NULL ;
+    GrB_Index *Tile_nrows = NULL ;
+    GrB_Matrix T = NULL ;
 
     GrB_Matrix C_3 = NULL,
 	       A = NULL,
@@ -149,10 +170,10 @@ int LAGraph_FastGraphletTransform
     // compute d_1 = Ae (in_degree)
     //--------------------------------------------------------------------------
 
-    GRB_TRY (GrB_Vector_new (&d_1, GrB_INT64, n)) ;
+//  GRB_TRY (GrB_Vector_new (&d_1, GrB_INT64, n)) ;
 
     // d_1 = Ae (in_degree)
-    GRB_TRY (LAGraph_Cached_OutDegree (G, msg)) ;
+    LG_TRY (LAGraph_Cached_OutDegree (G, msg)) ;
 
     GRB_TRY (GrB_Vector_dup (&d_1, G->out_degree)) ;
 
@@ -172,7 +193,6 @@ int LAGraph_FastGraphletTransform
 
     GRB_TRY (GrB_Vector_new (&d_3, GrB_INT64, n)) ;
 
-    GrB_UnaryOp Sub_one_mult = NULL ;
     GRB_TRY (GrB_UnaryOp_new (&Sub_one_mult, F_UNARY (sub_one_mult), GrB_INT64, GrB_INT64)) ;
 
     GRB_TRY (GrB_apply (d_3, NULL, NULL, Sub_one_mult, d_1, NULL)) ;
@@ -295,15 +315,17 @@ int LAGraph_FastGraphletTransform
 
     const GrB_Index entries_per_tile = 1000;
     GrB_Index ntiles = (nvals + entries_per_tile - 1) / entries_per_tile ;
-    GrB_Matrix A_Tiles [ntiles], D_Tiles [ntiles], C_Tiles [ntiles] ;
-    GrB_Index Tile_nrows [ntiles] ;
+    // FIXME: use LAGraph_Calloc here, and check if out of memory:
+    A_Tiles = calloc (ntiles , sizeof (GrB_Matrix)) ;
+    D_Tiles = calloc (ntiles , sizeof (GrB_Matrix)) ;
+    C_Tiles = calloc (ntiles , sizeof (GrB_Matrix)) ;
+    Tile_nrows = calloc (ntiles , sizeof (GrB_Index)) ;
     GrB_Index Tile_ncols [1] = {n} ;
 
     int64_t tot_deg = 0 ;
-    int tile_cnt = 0 ;
     GrB_Index last_row = -1 ;
     for (GrB_Index i = 0; i < n; ++i) {
-        int64_t deg ;
+        int64_t deg = 0 ;
         GRB_TRY (GrB_Vector_extractElement (&deg, d_1, i)) ;
 
         if (i == n - 1 || (tot_deg / entries_per_tile != (tot_deg + deg) / entries_per_tile)) {
@@ -317,18 +339,17 @@ int LAGraph_FastGraphletTransform
     GRB_TRY (GxB_Matrix_split (A_Tiles, tile_cnt, 1, Tile_nrows, Tile_ncols, A, NULL)) ;
     GRB_TRY (GxB_Matrix_split (D_Tiles, tile_cnt, 1, Tile_nrows, Tile_ncols, D_1, NULL)) ;
 
-    for (int i = 0; i < tile_cnt; ++i) C_Tiles [i] = NULL ;
-
-#define TRY(method)                     \
-    {                                   \
-        GrB_Info info = method ;        \
-        if (info != GrB_SUCCESS)        \
-        {                               \
-            GrB_free (&A_i) ;           \
-            GrB_free (&C_Tiles [i]) ;   \
-            GrB_free (&e) ;             \
-            continue ;                  \
-        }                               \
+#define TRY(method)                         \
+    {                                       \
+        GrB_Info info2 = method ;           \
+        if (info2 != GrB_SUCCESS)           \
+        {                                   \
+            GrB_free (&A_i) ;               \
+            GrB_free (&C_Tiles [i_tile]) ;  \
+            GrB_free (&e) ;                 \
+            info1 = info2 ;                 \
+            continue ;                      \
+        }                                   \
     }
 
 //  GxB_set (GxB_NTHREADS, 1) ;
@@ -336,27 +357,31 @@ int LAGraph_FastGraphletTransform
     LG_TRY (LAGraph_GetNumThreads (&save_nthreads_outer, &save_nthreads_inner, msg)) ;
     LG_TRY (LAGraph_SetNumThreads (1, 1, msg)) ;
 
+    int i_tile;
+    GrB_Info info1 = GrB_SUCCESS ;
     #pragma omp parallel for num_threads(omp_get_max_threads()) schedule(dynamic,1)
-    for (int i = 0; i < tile_cnt; ++i) {
+    for (i_tile = 0; i_tile < tile_cnt; ++i_tile) {
         GrB_Matrix A_i = NULL, e = NULL ;
 
         TRY (GrB_Matrix_new (&e, GrB_INT64, n, 1)) ;
         TRY (GrB_assign (e, NULL, NULL, (int64_t) 1, GrB_ALL, n, GrB_ALL, 1, NULL)) ;
 
-        TRY (GrB_Matrix_new (&A_i, GrB_INT64, Tile_nrows [i], n)) ;
-        TRY (GrB_Matrix_new (&C_Tiles [i], GrB_INT64, Tile_nrows [i], 1)) ;
+        TRY (GrB_Matrix_new (&A_i, GrB_INT64, Tile_nrows [i_tile], n)) ;
+        TRY (GrB_Matrix_new (&C_Tiles [i_tile], GrB_INT64, Tile_nrows [i_tile], 1)) ;
 
-        TRY (GrB_mxm (A_i, NULL, NULL, GxB_PLUS_PAIR_INT64, A_Tiles [i], A, NULL)) ;
-        TRY (GrB_eWiseAdd (A_i, NULL, NULL, GrB_MINUS_INT64, A_i, D_Tiles [i], NULL)) ;
+        TRY (GrB_mxm (A_i, NULL, NULL, GxB_PLUS_PAIR_INT64, A_Tiles [i_tile], A, NULL)) ;
+        TRY (GrB_eWiseAdd (A_i, NULL, NULL, GrB_MINUS_INT64, A_i, D_Tiles [i_tile], NULL)) ;
         TRY (GrB_apply (A_i, NULL, NULL, Sub_one_mult, A_i, NULL)) ;
 
         // multiply A_i by it on the right
-        TRY (GrB_mxm (C_Tiles [i], NULL, NULL, GxB_PLUS_FIRST_INT64, A_i, e, NULL)) ;
+        TRY (GrB_mxm (C_Tiles [i_tile], NULL, NULL, GxB_PLUS_FIRST_INT64, A_i, e, NULL)) ;
 
         GrB_free (&A_i) ;
         GrB_free (&e) ;
-
     }
+
+    GRB_TRY (info1) ;
+
 //  GxB_set (GxB_NTHREADS, omp_get_max_threads()) ;
     LG_TRY (LAGraph_SetNumThreads (save_nthreads_outer, save_nthreads_inner, msg)) ;
 
@@ -406,10 +431,9 @@ int LAGraph_FastGraphletTransform
     //--------------------------------------------------------------------------
 
     if (compute_d_15) {
-        LAGRAPH_TRY (LAGraph_KTruss (&A, G, 4, msg)) ;
+        LG_TRY (LAGraph_KTruss (&T, G, 4, msg)) ;
         GRB_TRY (GrB_Vector_new (&d_15, GrB_INT64, n)) ;
 
-        //GrB_wait (A, GrB_MATERIALIZE) ;     // this is essential
         int nthreads = 1 ;
         // todo: parallelize this...
 //#pragma omp parallel for num_threads(nthreads)
@@ -426,32 +450,32 @@ int LAGraph_FastGraphletTransform
             }
 
 
-            // thread tid operates on A(row1:row2-1,:)
+            // thread tid operates on T(row1:row2-1,:)
             GrB_Index row1 = 0;//tid * (n / nthreads) ;
             GrB_Index row2 = n;//(tid == nthreads - 1) ? n : ((tid+1) * (n / nthreads)) ;
 
             GxB_Iterator riterator ;
             GxB_Iterator_new (&riterator) ;
-            GRB_TRY (GxB_rowIterator_attach (riterator, A, NULL)) ;
+            GRB_TRY (GxB_rowIterator_attach (riterator, T, NULL)) ;
 
             GxB_Iterator iterator ;
             GxB_Iterator_new (&iterator) ;
-            GRB_TRY (GxB_rowIterator_attach (iterator, A, NULL)) ;
+            GRB_TRY (GxB_rowIterator_attach (iterator, T, NULL)) ;
 
-            // seek to A(row1,:)
+            // seek to T(row1,:)
             GrB_Info info = GxB_rowIterator_seekRow (iterator, row1) ;
             while (info != GxB_EXHAUSTED)
             {
-                // iterate over entries in A(i,:)
-                GrB_Index i = GxB_rowIterator_getRowIndex (iterator) ;
-                if (i >= row2) break ;
+                // iterate over entries in T(i,:)
+                GrB_Index idx2 = GxB_rowIterator_getRowIndex (iterator) ;
+                if (idx2 >= row2) break ;
                 int neighbor_cnt = 0 ;
                 while (info == GrB_SUCCESS)
                 {
-                    // working with edge (i, j)
+                    // working with edge (idx2, j)
                     GrB_Index j = GxB_rowIterator_getColIndex (iterator) ;
 
-                    if (j > i) {
+                    if (j > idx2) {
                         neighbors [neighbor_cnt++] = j ;
                         isNeighbor [j] = 1 ;
                     }
@@ -480,7 +504,7 @@ int LAGraph_FastGraphletTransform
                         while (info == GrB_SUCCESS) { // iterate over neighbors of k
                             GrB_Index l = GxB_rowIterator_getColIndex (riterator) ;
                             if (l > k && isNeighbor [l] == -1) {
-                                f15[i]++ ;
+                                f15[idx2]++ ;
                                 f15[j]++ ;
                                 f15[k]++ ;
                                 f15[l]++ ;
@@ -498,11 +522,12 @@ int LAGraph_FastGraphletTransform
                     isNeighbor [j] = 0 ;
                 }
 
-                // move to the next row, A(i+1,:)
+                // move to the next row, T(i+1,:)
                 info = GxB_rowIterator_nextRow (iterator) ;
             }
             GrB_free (&iterator) ;
             GrB_free (&riterator) ;
+            GrB_free (&T) ;
             GRB_TRY (GrB_Vector_build (d_15, I, f15, n, NULL)) ;
 
             free (neighbors) ;
@@ -566,6 +591,10 @@ int LAGraph_FastGraphletTransform
     //--------------------------------------------------------------------------
 
     LG_FREE_WORK ;
+    free ((void *) A_Tiles) ;       A_Tiles = NULL ;
+    free ((void *) D_Tiles) ;       D_Tiles = NULL ;
+    free ((void *) C_Tiles) ;       C_Tiles = NULL ;
+    free ((void *) Tile_nrows) ;    Tile_nrows = NULL ;
 
     return (0) ;
 #endif
diff --git a/experimental/algorithm/LAGraph_MaximalIndependentSet.c b/experimental/algorithm/LAGraph_MaximalIndependentSet.c
index 8e30a6abd7..80f70fe274 100644
--- a/experimental/algorithm/LAGraph_MaximalIndependentSet.c
+++ b/experimental/algorithm/LAGraph_MaximalIndependentSet.c
@@ -27,6 +27,7 @@
     GrB_free (&empty) ;             \
     GrB_free (&Seed) ;              \
     GrB_free (&score) ;             \
+    GrB_free (&degree) ;            \
 }
 
 #define LG_FREE_ALL                 \
diff --git a/experimental/algorithm/LAGraph_SquareClustering.c b/experimental/algorithm/LAGraph_SquareClustering.c
index 0e11b46625..cb4c6518e3 100644
--- a/experimental/algorithm/LAGraph_SquareClustering.c
+++ b/experimental/algorithm/LAGraph_SquareClustering.c
@@ -79,13 +79,14 @@
 {                                   \
     GrB_free (&squares) ;           \
     GrB_free (&denom) ;             \
+    GrB_free (&neg_denom) ;         \
+    GrB_free (&P2) ;                \
+    GrB_free (&D) ;                 \
 }
 
 #define LG_FREE_ALL                 \
 {                                   \
     LG_FREE_WORK ;                  \
-    GrB_free (&D) ;                 \
-    GrB_free (&P2) ;                \
     GrB_free (&r) ;                 \
 }
 
diff --git a/experimental/algorithm/LAGraph_cc_lacc.c b/experimental/algorithm/LAGraph_cc_lacc.c
index 7cc590c386..97c5e1eb37 100644
--- a/experimental/algorithm/LAGraph_cc_lacc.c
+++ b/experimental/algorithm/LAGraph_cc_lacc.c
@@ -25,6 +25,7 @@
 {                           \
     free(I);                \
     free(V);                \
+    GrB_free (&S2) ;        \
     GrB_free (&stars);      \
     GrB_free (&mask);       \
     GrB_free (&parents);    \
@@ -91,6 +92,7 @@ int LAGraph_cc_lacc
     GrB_Vector tmp = NULL, pNonstars = NULL, nsgp = NULL; // temporary
     GrB_Index *I = NULL;
     GrB_Index *V = NULL;
+    GrB_Matrix S = NULL, S2 = NULL ;
 
     GrB_Index n ;
     GRB_TRY (GrB_Matrix_nrows (&n, A)) ;
@@ -99,11 +101,11 @@ int LAGraph_cc_lacc
     //printf ("number of nodes: %g\n", (double) n) ;
     //printf ("number of edges: %g\n", (double) nnz) ;
 
-    GrB_Matrix S = NULL;
     if (sanitize)
     {
-        GRB_TRY (GrB_Matrix_new (&S, GrB_BOOL, n, n)) ;
-        GRB_TRY (GrB_eWiseAdd (S, NULL, NULL, GrB_LOR, A, A, GrB_DESC_T1)) ;
+        GRB_TRY (GrB_Matrix_new (&S2, GrB_BOOL, n, n)) ;
+        GRB_TRY (GrB_eWiseAdd (S2, NULL, NULL, GrB_LOR, A, A, GrB_DESC_T1)) ;
+        S = S2 ;
     }
     else
     {
diff --git a/experimental/algorithm/LAGraph_cdlp.c b/experimental/algorithm/LAGraph_cdlp.c
index c800119020..e1d83c7012 100644
--- a/experimental/algorithm/LAGraph_cdlp.c
+++ b/experimental/algorithm/LAGraph_cdlp.c
@@ -213,7 +213,7 @@ int LAGraph_cdlp
         LAGRAPH_TRY (LAGraph_Malloc ((void **) &AJ, nz, sizeof(GrB_Index),msg));
         GRB_TRY (GrB_Matrix_extractTuples_UINT64(AI, AJ, GrB_NULL, &nz, A))
 
-        LAGRAPH_TRY (LAGraph_Malloc ((void **) &AX, nz, sizeof(GrB_Index),msg));
+        LAGRAPH_TRY (LAGraph_Calloc ((void **) &AX, nz, sizeof(GrB_Index),msg));
         GRB_TRY (GrB_Matrix_new(&S, GrB_UINT64, n, n));
         GRB_TRY (GrB_Matrix_build(S, AI, AJ, AX, nz, GrB_PLUS_UINT64));
 
@@ -234,6 +234,7 @@ int LAGraph_cdlp
     GRB_TRY (GxB_get(GxB_FORMAT, &global_format))
     if (A_format != GxB_BY_ROW || global_format != GxB_BY_ROW)
     {
+        LG_FREE_ALL;
         return (GrB_INVALID_VALUE) ;
     }
 #endif
diff --git a/experimental/algorithm/LAGraph_lcc.c b/experimental/algorithm/LAGraph_lcc.c
index 3586ae49b9..84f4dccf5d 100644
--- a/experimental/algorithm/LAGraph_lcc.c
+++ b/experimental/algorithm/LAGraph_lcc.c
@@ -64,9 +64,9 @@
 
 #define LG_FREE_ALL                 \
 {                                   \
-    GrB_free (&C) ;                 \
+    GrB_free (&A2) ;                \
+    GrB_free (&C2) ;                \
     GrB_free (&CL) ;                \
-    if (sanitize) GrB_free (&S) ;   \
     GrB_free (&U) ;                 \
     GrB_free (&W) ;                 \
     GrB_free (&LCC) ;               \
@@ -133,7 +133,8 @@ int LAGraph_lcc            // compute lcc for all nodes in A
     }
 
     GrB_Matrix C = NULL, CL = NULL, S = NULL, U = NULL ;
-    GrB_Vector W = NULL, LCC = NULL ;
+    GrB_Vector W = NULL, LCC = NULL ; 
+    GrB_Matrix A2 = NULL, C2 = NULL ;
     GrB_UnaryOp LAGraph_COMB_DIR_FP64 = NULL ;
     GrB_UnaryOp LAGraph_COMB_UNDIR_FP64 = NULL ;
     GrB_Info info ;
@@ -167,12 +168,13 @@ int LAGraph_lcc            // compute lcc for all nodes in A
         t [0] = LAGraph_WallClockTime ( ) ;
 
         // S = binary structure of A
-        GrB_Matrix_new (&S, GrB_FP64, n, n) ;
-        GrB_apply (S, NULL, NULL, GrB_ONEB_FP64, A, 0, NULL) ;
+        GRB_TRY (GrB_Matrix_new (&A2, GrB_FP64, n, n)) ;
+        GRB_TRY (GrB_apply (A2, NULL, NULL, GrB_ONEB_FP64, A, 0, NULL)) ;
 
         // remove all self edges
-        GrB_select (S, NULL, NULL, GrB_OFFDIAG, S, 0, NULL) ;
+        GRB_TRY (GrB_select (A2, NULL, NULL, GrB_OFFDIAG, A2, 0, NULL)) ;
         t [0] = LAGraph_WallClockTime ( ) - t [0] ;
+        S = A2 ;
     }
     else
     {
@@ -195,13 +197,11 @@ int LAGraph_lcc            // compute lcc for all nodes in A
                                  F_UNARY (LAGraph_comb_undir_fp64),
                                  GrB_FP64, GrB_FP64)) ;
 
-    GRB_TRY (GrB_Matrix_new (&C, GrB_FP64, n, n)) ;
     GRB_TRY (GrB_Matrix_new (&U, GrB_UINT32, n, n)) ;
 
     if (symmetric)
     {
         C = S ;
-        S = NULL ;
 
         //----------------------------------------------------------------------
         // U = triu(C)
@@ -221,7 +221,8 @@ int LAGraph_lcc            // compute lcc for all nodes in A
         // C = A \/ A' to create an undirected graph C
         //----------------------------------------------------------------------
 
-        GRB_TRY (GrB_Matrix_new (&C, GrB_FP64, n, n)) ;
+        GRB_TRY (GrB_Matrix_new (&C2, GrB_FP64, n, n)) ;
+        C = C2 ;
         GRB_TRY (GrB_eWiseAdd (C, NULL, NULL, GrB_LOR, S, AT, NULL)) ;
 
         //----------------------------------------------------------------------
@@ -232,7 +233,6 @@ int LAGraph_lcc            // compute lcc for all nodes in A
         GRB_TRY (GrB_eWiseAdd (D, NULL, NULL, GrB_PLUS_FP64, S, AT, NULL)) ;
 
         GrB_free (&AT) ;
-        if (sanitize) GrB_free (&S) ;
 
         //----------------------------------------------------------------------
         // U = triu(D)
diff --git a/experimental/algorithm/LG_CC_FastSV5.c b/experimental/algorithm/LG_CC_FastSV5.c
index 87aecfdcc6..68ac423509 100644
--- a/experimental/algorithm/LG_CC_FastSV5.c
+++ b/experimental/algorithm/LG_CC_FastSV5.c
@@ -211,8 +211,9 @@ static inline int Reduce_assign32
         ht_init (ht_key, ht_val) ;
         ht_sample (index, n, HASH_SAMPLES, ht_key, ht_val, seed) ;
 
+        int tid;
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             // get the thread-specific buf array of size HASH_SIZE
             // todo: buf is a bad variable name; it's not a "buffer",
@@ -260,7 +261,7 @@ static inline int Reduce_assign32
             int32_t i = ht_key [h] ;
             if (i != -1)
             {
-                for (int32_t tid = 0 ; tid < nthreads ; tid++)
+                for (tid = 0 ; tid < nthreads ; tid++)
                 {
                     w_x [i] = LAGRAPH_MIN (w_x [i], mem [tid * HASH_SIZE + h]) ;
                 }
@@ -394,8 +395,9 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
     LAGRAPH_TRY (LAGraph_Malloc ((void **) &V32, n, sizeof (uint32_t), msg)) ;
 
     // prepare vectors
+    int64_t i;
     #pragma omp parallel for num_threads(nthreads2) schedule(static)
-    for (GrB_Index i = 0 ; i < n ; i++)
+    for (i = 0 ; i < n ; i++)
     {
         I [i] = i ;
         V32 [i] = (uint32_t) i ;
@@ -487,8 +489,9 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // determine the number entries to be constructed in T for each thread
         //----------------------------------------------------------------------
 
+        int tid;
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             for (int32_t i = range [tid] ; i < range [tid+1] ; i++)
             {
@@ -501,7 +504,7 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // count = cumsum (count)
         //----------------------------------------------------------------------
 
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             count [tid + 1] += count [tid] ;
         }
@@ -518,7 +521,7 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // Note that Tx is not modified.  Only Tp and Tj are constructed.
 
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index p = count [tid] ;
             Tp [range [tid]] = p ;
@@ -575,8 +578,9 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
             // calculate grandparent
             // fixme: NULL parameter is SS:GrB extension
             GRB_TRY (GrB_Vector_extractTuples (NULL, V32, &n, f)) ; // fixme
+            int32_t i;
             #pragma omp parallel for num_threads(nthreads2) schedule(static)
-            for (uint32_t i = 0 ; i < n ; i++)
+            for (i = 0 ; i < n ; i++)
             {
                 I [i] = (GrB_Index) V32 [i] ;
             }
@@ -630,7 +634,7 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // scheduled.
 
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index ptr = Sp [range [tid]] ;
             // thread tid scans S (range [tid]:range [tid+1]-1,:),
@@ -668,17 +672,32 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // Compact empty space out of Tj not filled in from the above phase.
         // This is a lot of work and should be done in parallel.
         GrB_Index offset = 0 ;
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
-            memcpy (Tj + offset, Tj + Tp [range [tid]],
+
+//          this memcpy is not safe (src/dest can overlap)
+//          memcpy (Tj + offset, Tj + Tp [range [tid]],
+//              sizeof (GrB_Index) * count [tid]) ;
+
+//          // using a for loop instead:
+//          GrB_Index *Tj_dest = Tj + offset ;
+//          GrB_Index *Tj_src  = Tj + Tp [range [tid]] ;
+//          for (int64_t k = 0 ; k < count [tid] ; k++)
+//          {
+//              Tj_dest [k] = Tj_src [k] ;
+//          }
+
+//          this is safe (memmove_s not necessary):
+            memmove (Tj + offset, Tj + Tp [range [tid]],
                 sizeof (GrB_Index) * count [tid]) ;
+
             offset += count [tid] ;
             count [tid] = offset - count [tid] ;
         }
 
         // Compact empty space out of Tp
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index ptr = Tp [range [tid]] ;
             for (int32_t i = range [tid] ; i < range [tid+1] ; i++)
@@ -736,8 +755,9 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
         // calculate grandparent
         // fixme: NULL parameter is SS:GrB extension
         GRB_TRY (GrB_Vector_extractTuples (NULL, V32, &n, f)) ; // fixme
+        int32_t k;
         #pragma omp parallel for num_threads(nthreads2) schedule(static)
-        for (uint32_t k = 0 ; k < n ; k++)
+        for (k = 0 ; k < n ; k++)
         {
             I [k] = (GrB_Index) V32 [k] ;
         }
diff --git a/experimental/benchmark/CMakeLists.txt b/experimental/benchmark/CMakeLists.txt
index e26887eeef..6cf1ca1c52 100644
--- a/experimental/benchmark/CMakeLists.txt
+++ b/experimental/benchmark/CMakeLists.txt
@@ -13,9 +13,9 @@
 
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/src/test/include
-    ${CMAKE_SOURCE_DIR}/src/benchmark
-    ${CMAKE_SOURCE_DIR}/experimental/test/include )
+include_directories ( ${PROJECT_SOURCE_DIR}/src/test/include
+    ${PROJECT_SOURCE_DIR}/src/benchmark
+    ${PROJECT_SOURCE_DIR}/experimental/test/include )
 
 file( GLOB DEMO_SOURCES LIST_DIRECTORIES false *_demo.c )
 foreach( demosourcefile ${DEMO_SOURCES} )
@@ -23,6 +23,14 @@ foreach( demosourcefile ${DEMO_SOURCES} )
     string( REPLACE ".c" "" demoname ${justname} )
 #   message("Adding: ${demoname}")
     add_executable( ${demoname} ${demosourcefile} )
-    target_link_libraries( ${demoname} lagraphx lagraph lagraphtest lagraphxtest ${GRAPHBLAS_LIBRARIES} )
-    target_link_directories( ${demoname} BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+    set_target_properties ( ${demoname} PROPERTIES
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries( ${demoname}
+            LAGraphX LAGraph lagraphtest lagraphxtest GraphBLAS::GraphBLAS )
+    else ( )
+        target_link_libraries( ${demoname}
+            LAGraphX_static LAGraph_static lagraphtest_static lagraphxtest_static GraphBLAS::GraphBLAS )
+    endif ( )
 endforeach( demosourcefile ${DEMO_SOURCES} )
diff --git a/experimental/benchmark/dnn_demo.c b/experimental/benchmark/dnn_demo.c
index 1c6e7a0195..12dbce2d26 100644
--- a/experimental/benchmark/dnn_demo.c
+++ b/experimental/benchmark/dnn_demo.c
@@ -236,8 +236,8 @@ int main (int argc, char **argv)
     // LAGraph_dnn, but it is exploited here, simply to reduce the time to load
     // the problems.
 
-    int len = 1024 ;
-    char filename [len] ;
+    #define FILENAME_LEN 1024
+    char filename [FILENAME_LEN] ;
 
     #define NMAXLAYERS 3
     int maxLayers [NMAXLAYERS] = { 120, 480, 1920 } ;
@@ -377,9 +377,10 @@ int main (int argc, char **argv)
             bool ok = true ;
 
             // assume the I/O system can handle 2-way parallelism
+            int layer;
             #pragma omp parallel for schedule(dynamic,1) reduction(&&:ok) \
                 num_threads (2)
-            for (int layer = first_layer ; layer < nlayers ; layer++)
+            for (layer = first_layer ; layer < nlayers ; layer++)
             {
                 // read the neuron layer: W [layer]
                 char my_filename [1024] ;
@@ -428,7 +429,7 @@ int main (int argc, char **argv)
             printf ("read net time %g sec\n", t) ;
 
             double nedges = 0 ;
-            for (int layer = 0 ; layer < nlayers ; layer++)
+            for (layer = 0 ; layer < nlayers ; layer++)
             {
                 GrB_Index nvals ;
                 GRB_TRY (GrB_Matrix_nvals (&nvals, W [layer])) ;
diff --git a/experimental/test/CMakeLists.txt b/experimental/test/CMakeLists.txt
index 7b54598b4b..51f99f0987 100644
--- a/experimental/test/CMakeLists.txt
+++ b/experimental/test/CMakeLists.txt
@@ -17,9 +17,9 @@
 # build the lagraphxtest library
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/src/test/include
-    ${CMAKE_SOURCE_DIR}/src/test/include
-    ${CMAKE_SOURCE_DIR}/experimental/test/include )
+include_directories ( ${PROJECT_SOURCE_DIR}/src/test/include
+    ${PROJECT_SOURCE_DIR}/src/test/include
+    ${PROJECT_SOURCE_DIR}/experimental/test/include )
 
 file ( GLOB LAGRAPHXTEST_LIB_SOURCES "LG_*.c" )
 
@@ -35,43 +35,52 @@ endif ( )
 # dynamic lagraphxtest library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphxtest SHARED ${LAGRAPHXTEST_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphxtest PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-set_property ( TARGET lagraphxtest PROPERTY C_STANDARD 11 )
-target_link_libraries(lagraphxtest PUBLIC lagraph lagraphtest ${GRAPHBLAS_LIBRARIES})
-target_link_directories( lagraphxtest BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+if ( BUILD_SHARED_LIBS )
+    add_library ( lagraphxtest SHARED ${LAGRAPHXTEST_LIB_SOURCES} )
+    set_target_properties ( lagraphxtest PROPERTIES
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/dlls )
+    target_link_libraries ( lagraphxtest PRIVATE LAGraph lagraphtest GraphBLAS::GraphBLAS )
+    target_compile_definitions ( lagraphxtest PRIVATE LGX_TEST_LIBRARY )
+    target_compile_definitions ( lagraphxtest PUBLIC LGX_TEST_DLL )
+endif ( )
 
 #-------------------------------------------------------------------------------
 # static lagraphxtest library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphxtest_static STATIC ${LAGRAPHXTEST_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphxtest_static PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    OUTPUT_NAME lagraphxtest
-    POSITION_INDEPENDENT_CODE OFF
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-
-if ( MSVC )
+if ( BUILD_STATIC_LIBS )
+    add_library ( lagraphxtest_static STATIC ${LAGRAPHXTEST_LIB_SOURCES} )
     set_target_properties ( lagraphxtest_static PROPERTIES
-        OUTPUT_NAME lagraphxtest_static )
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        OUTPUT_NAME lagraphxtest
+        POSITION_INDEPENDENT_CODE OFF
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+
+    if ( MSVC )
+        set_target_properties ( lagraphxtest_static PROPERTIES
+            OUTPUT_NAME lagraphxtest_static )
+    endif ( )
+
+    target_link_libraries ( lagraphxtest_static PRIVATE LAGraph_static lagraphtest_static GraphBLAS::GraphBLAS )
 endif ( )
 
-set_property ( TARGET lagraphxtest_static PROPERTY C_STANDARD 11 )
-target_link_libraries(lagraphxtest_static PUBLIC lagraph lagraphtest ${GRAPHBLAS_LIBRARIES})
-target_link_directories( lagraphxtest_static BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-
 #-------------------------------------------------------------------------------
 # add OpenMP
 #-------------------------------------------------------------------------------
 
-if ( OPENMP_FOUND )
-    target_link_libraries ( lagraphxtest PUBLIC ${OpenMP_C_LIBRARIES} )
-    target_link_libraries ( lagraphxtest_static PUBLIC ${OpenMP_C_LIBRARIES} )
+if ( OpenMP_C_FOUND )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries ( lagraphxtest PRIVATE OpenMP::OpenMP_C )
+    endif ( )
+    if ( BUILD_STATIC_LIBS )
+        target_link_libraries ( lagraphxtest_static PRIVATE OpenMP::OpenMP_C )
+    endif ( )
 endif ( )
 
 
@@ -85,9 +94,27 @@ foreach( testsourcefile ${TEST_SOURCES} )
     string( REPLACE ".c" "" testname ${justname} )
 #   message("Adding: ${testname}")
     add_executable( ${testname} ${testsourcefile} )
-    target_link_libraries( ${testname} lagraphx lagraph lagraphxtest lagraphtest ${GRAPHBLAS_LIBRARIES} )
-    target_link_directories( ${testname} BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-    string( REPLACE "test_" "ctest_" ctestname ${testname})
-    add_test( ${ctestname} ${testname})
+    set_target_properties ( ${testname} PROPERTIES
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries( ${testname}
+            LAGraphX LAGraph lagraphxtest lagraphtest GraphBLAS::GraphBLAS )
+    else ( )
+        target_link_libraries( ${testname}
+            LAGraphX_static LAGraph_static lagraphxtest_static lagraphtest_static GraphBLAS::GraphBLAS )
+    endif ( )
+    string( REPLACE "test_" "LAGraphX_" ctestname ${testname})
+    add_test( NAME ${ctestname} COMMAND $<TARGET_FILE:${testname}> )
+#   add_test( NAME ${ctestname} COMMAND valgrind $<TARGET_FILE:${testname}> )
+    if (WIN32)
+        if ( BUILD_SHARED_LIBS )
+            set_tests_properties ( ${ctestname} PROPERTIES
+                ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:GraphBLAS::GraphBLAS>;PATH=path_list_prepend:$<TARGET_FILE_DIR:lagraphxtest>" )
+        else ( )
+            set_tests_properties ( ${ctestname} PROPERTIES
+                ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:GraphBLAS::GraphBLAS>" )
+        endif ( )
+    endif ( )
 endforeach( testsourcefile ${TEST_SOURCES} )
 
diff --git a/experimental/test/LG_check_kcore.c b/experimental/test/LG_check_kcore.c
index 00e507f41d..8ef56faa64 100644
--- a/experimental/test/LG_check_kcore.c
+++ b/experimental/test/LG_check_kcore.c
@@ -21,6 +21,10 @@
 
 #define LG_FREE_ALL                             \
 {                                               \
+    LAGraph_Free ((void **) &vert, msg) ;       \
+    LAGraph_Free ((void **) &deg, msg) ;        \
+    LAGraph_Free ((void **) &bin, msg) ;        \
+    LAGraph_Free ((void **) &pos, msg) ;        \
     LAGraph_Free ((void **) &Ap, msg) ;         \
     LAGraph_Free ((void **) &Aj, msg) ;         \
     LAGraph_Free ((void **) &Ax, msg) ;         \
@@ -48,7 +52,8 @@ int LG_check_kcore
     //--------------------------------------------------------------------------
 
     LG_CLEAR_MSG ;
-
+    uint64_t *vert = NULL, *pos = NULL, *bin = NULL, *deg = NULL ;
+    uint64_t maxDeg = 0;
     GrB_Index *Ap = NULL, *Aj = NULL, *Ai = NULL ;
     void *Ax = NULL ;
     GrB_Index Ap_size, Aj_size, Ax_size, n, ncols, Ap_len, Aj_len, Ax_len ;
@@ -78,8 +83,7 @@ int LG_check_kcore
     //printf("ap_len = %ld, aj_len = %ld, ax_len = %ld\n", Ap_len, Aj_len, Ax_len) ;
 
     //create the arrays
-    uint64_t *vert = NULL, *pos = NULL, *bin = NULL, *deg = NULL /*, *core = NULL */;
-    uint64_t maxDeg = 0;
+
     LAGraph_Malloc((void **) &deg, n, sizeof(uint64_t), msg) ;
     LAGraph_Malloc((void **) &vert, n, sizeof(uint64_t), msg) ;
     LAGraph_Malloc((void **) &pos, n, sizeof(uint64_t), msg) ;
diff --git a/experimental/test/LG_check_ktruss.c b/experimental/test/LG_check_ktruss.c
index 31945c7a1b..e5dfb33e8e 100644
--- a/experimental/test/LG_check_ktruss.c
+++ b/experimental/test/LG_check_ktruss.c
@@ -105,10 +105,11 @@ int LG_check_ktruss
         //----------------------------------------------------------------------
 
         // masked dot-product method: C{C}=C*C' using the PLUS_ONE semiring
+        int64_t i;
         #if !defined ( COVERAGE )
         #pragma omp parallel for schedule(dynamic,1024)
         #endif
-        for (int64_t i = 0 ; i < n ; i++)
+        for (i = 0 ; i < n ; i++)
         {
             // for each entry in C(i,:)
             for (int64_t p = Cp [i] ; p < Cp [i+1] ; p++)
diff --git a/experimental/test/test_AllKCore.c b/experimental/test/test_AllKCore.c
index 58f75512a3..439787b94b 100644
--- a/experimental/test/test_AllKCore.c
+++ b/experimental/test/test_AllKCore.c
@@ -116,6 +116,8 @@ void test_AllKCore (void)
         TEST_CHECK(km1 == km2) ;
         OK (LAGraph_Vector_IsEqual (&ok, c1, c2, msg)) ;
         TEST_CHECK (ok) ;
+        GrB_free (&c1) ;
+        GrB_free (&c2) ;
 
         OK (LAGraph_Delete (&G, msg)) ;
     }
diff --git a/experimental/test/test_BF.c b/experimental/test/test_BF.c
index 3d942d4a72..e5e88ff4e6 100644
--- a/experimental/test/test_BF.c
+++ b/experimental/test/test_BF.c
@@ -312,6 +312,7 @@ void test_BF (void)
                 LAGraph_Free ((void **) &pi10, NULL) ;
                 result = LAGraph_BF_pure_c (&d10, &pi10, s, n, nvals,
                     (const int64_t *) I, (const int64_t *) J, W_int32) ;
+                LAGraph_Free ((void **) &pi10, NULL) ;
                 TEST_CHECK (result == valid) ;
             }
 
@@ -498,6 +499,7 @@ void test_BF (void)
         GrB_free (&d9) ;
         GrB_free (&pi6) ;
         GrB_free (&h6) ;
+        LAGraph_Free ((void **) &d10, NULL) ;
     }
 
     teardown ( ) ;
diff --git a/experimental/test/test_KTruss.c b/experimental/test/test_KTruss.c
index bbb4652650..8bb75100fb 100644
--- a/experimental/test/test_KTruss.c
+++ b/experimental/test/test_KTruss.c
@@ -124,6 +124,8 @@ void test_ktruss (void)
         OK (LG_check_ktruss (&C2, G, 3, msg)) ;
         OK (LAGraph_Matrix_IsEqual (&ok, C1, C2, msg)) ;
         TEST_CHECK (ok) ;
+        OK (GrB_free (&C1)) ;
+        OK (GrB_free (&C2)) ;
 
         OK (LAGraph_Delete (&G, msg)) ;
     }
diff --git a/experimental/test/test_MaximalIndependentSet.c b/experimental/test/test_MaximalIndependentSet.c
index feeb4c33e2..95db12c42f 100644
--- a/experimental/test/test_MaximalIndependentSet.c
+++ b/experimental/test/test_MaximalIndependentSet.c
@@ -100,6 +100,7 @@ void test_MIS (void)
 
         // C = structure of A
         OK (LAGraph_Matrix_Structure (&C, A, msg)) ;
+        OK (GrB_free (&A)) ;
 
         // construct a directed graph G with adjacency matrix C
         OK (LAGraph_New (&G, &C, LAGraph_ADJACENCY_DIRECTED, msg)) ;
diff --git a/experimental/test/test_SWrite.c b/experimental/test/test_SWrite.c
index 53d883e1c8..58d00cc9e2 100644
--- a/experimental/test/test_SWrite.c
+++ b/experimental/test/test_SWrite.c
@@ -288,7 +288,7 @@ void test_SWrite_errors (void)
     TEST_CHECK (result == GrB_INVALID_VALUE) ;
     fclose (f) ;
 
-    f = fopen ("error.lagraph", "w") ;
+    f = fopen ("error.lagraph", "wb") ;
     TEST_CHECK (f != NULL) ;
 
     result = LAGraph_SWrite_HeaderStart (f, NULL, msg) ;
diff --git a/experimental/test/test_TriangleCentrality.c b/experimental/test/test_TriangleCentrality.c
index e1bcba3239..af7f1216b4 100644
--- a/experimental/test/test_TriangleCentrality.c
+++ b/experimental/test/test_TriangleCentrality.c
@@ -117,6 +117,7 @@ void test_TriangleCentrality (void)
         G->kind = LAGraph_ADJACENCY_DIRECTED ;
         OK (LAGraph_VertexCentrality_Triangle (&c, &ntri, 0, G, msg)) ;
         TEST_CHECK (ntri == ntriangles) ;
+        GrB_free (&c) ;
 
         OK (LAGraph_Delete (&G, msg)) ;
     }
diff --git a/experimental/test/test_cdlp.c b/experimental/test/test_cdlp.c
index 26a5170188..33e99d1d68 100644
--- a/experimental/test/test_cdlp.c
+++ b/experimental/test/test_cdlp.c
@@ -182,6 +182,7 @@ void test_cdlp (void)
             bool ok = false ;
             OK (LAGraph_Vector_IsEqual (&ok, c, cgood, msg)) ;
             TEST_CHECK (ok) ;
+            OK (GrB_free (&cgood)) ;
         }
 
         printf ("\ncdlp:\n") ;
diff --git a/experimental/test/test_dnn.c b/experimental/test/test_dnn.c
index f171ba1e7b..ea2edaa919 100644
--- a/experimental/test/test_dnn.c
+++ b/experimental/test/test_dnn.c
@@ -140,6 +140,7 @@ void test_dnn (void)
     OK (GrB_Col_extract (TrueCategories, NULL, NULL, T, GrB_ALL,
         nfeatures_subset, 0, NULL)) ;
     OK (LAGraph_Vector_Print (TrueCategories, LAGraph_COMPLETE, stdout, msg)) ;
+    GrB_free (&T) ;
 
     //--------------------------------------------------------------------------
     // solve the problem
diff --git a/experimental/test/test_lcc.c b/experimental/test/test_lcc.c
index d96ee9b52f..55f66d0c32 100644
--- a/experimental/test/test_lcc.c
+++ b/experimental/test/test_lcc.c
@@ -182,6 +182,7 @@ void test_lcc (void)
             OK (GrB_reduce (&err, NULL, GrB_MAX_MONOID_FP64, cgood, NULL)) ;
             printf ("err: %g\n", err) ;
             TEST_CHECK (err < 1e-6) ;
+            OK (GrB_free (&cgood)) ;
         }
 
         printf ("\nlcc:\n") ;
diff --git a/experimental/test/test_msf.c b/experimental/test/test_msf.c
index f914793dfc..bf11e354c5 100644
--- a/experimental/test/test_msf.c
+++ b/experimental/test/test_msf.c
@@ -82,6 +82,7 @@ void test_msf (void)
         OK (GrB_assign (S, NULL, NULL, A, GrB_ALL, nrows, GrB_ALL, ncols,
             NULL)) ;
         GrB_Index n = nrows ;
+        OK (GrB_free (&A)) ;
 
         // construct a directed graph G with adjacency matrix S
         OK (LAGraph_New (&G, &S, LAGraph_ADJACENCY_DIRECTED, msg)) ;
@@ -112,6 +113,7 @@ void test_msf (void)
             bool ok = false ;
             OK (LAGraph_Matrix_IsEqual (&ok, C, Cgood, msg)) ;
             TEST_CHECK (ok) ;
+            OK (GrB_free (&Cgood)) ;
         }
 
         printf ("\nmsf:\n") ;
diff --git a/experimental/test/test_scc.c b/experimental/test/test_scc.c
index cea92e42ff..5829077a85 100644
--- a/experimental/test/test_scc.c
+++ b/experimental/test/test_scc.c
@@ -141,6 +141,7 @@ void test_scc (void)
             bool ok = false ;
             OK (LAGraph_Vector_IsEqual (&ok, c, cgood, msg)) ;
             TEST_CHECK (ok) ;
+            OK (GrB_free (&cgood)) ;
         }
 
         printf ("\nscc:\n") ;
diff --git a/experimental/utility/LAGraph_SLoadSet.c b/experimental/utility/LAGraph_SLoadSet.c
index e5b7a71bf0..b0485f584a 100644
--- a/experimental/utility/LAGraph_SLoadSet.c
+++ b/experimental/utility/LAGraph_SLoadSet.c
@@ -91,7 +91,7 @@ int LAGraph_SLoadSet            // load a set of matrices from a *.lagraph file
 
     if (filename != NULL)
     {
-        f = fopen (filename, "r") ;
+        f = fopen (filename, "rb") ;
         LG_ASSERT_MSG (f != NULL,
             LAGRAPH_IO_ERROR, "unable to open input file") ;
     }
diff --git a/experimental/utility/LAGraph_SSaveSet.c b/experimental/utility/LAGraph_SSaveSet.c
index 19d9fe8fd4..843109c993 100644
--- a/experimental/utility/LAGraph_SSaveSet.c
+++ b/experimental/utility/LAGraph_SSaveSet.c
@@ -77,7 +77,7 @@ int LAGraph_SSaveSet            // save a set of matrices from a *.lagraph file
     GRB_TRY (GxB_set (desc, GxB_COMPRESSION, GxB_COMPRESSION_LZ4HC + 9)) ;
     #endif
 
-    f = fopen (filename, "w") ;
+    f = fopen (filename, "wb") ;
     LG_ASSERT_MSG (f != NULL, -1001, "unable to create output file") ;
 
     //--------------------------------------------------------------------------
diff --git a/include/LAGraph.h b/include/LAGraph.h
index 5d5ddafc97..46a4f45a6d 100644
--- a/include/LAGraph.h
+++ b/include/LAGraph.h
@@ -2,7 +2,7 @@
 // LAGraph.h: user-visible include file for LAGraph
 //------------------------------------------------------------------------------
 
-// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 //
 // For additional details (including references to third party source code and
@@ -37,10 +37,10 @@
 // See also the LAGraph_Version utility method, which returns these values.
 // These definitions are derived from LAGraph/CMakeLists.txt.
 
-#define LAGRAPH_DATE "Aug 2, 2023"
+#define LAGRAPH_DATE "Dec 30, 2023"
 #define LAGRAPH_VERSION_MAJOR  1
-#define LAGRAPH_VERSION_MINOR  0
-#define LAGRAPH_VERSION_UPDATE 2
+#define LAGRAPH_VERSION_MINOR  1
+#define LAGRAPH_VERSION_UPDATE 0
 
 //==============================================================================
 // include files and helper macros
@@ -66,17 +66,17 @@
     #error "The GraphBLAS library must support the v2.0 C API Specification"
 #endif
 
-#if ( _MSC_VER && !__INTEL_COMPILER )
+#if ( _MSC_VER && !__INTEL_COMPILER && LG_DLL )
     #ifdef LG_LIBRARY
         // compiling LAGraph itself, exporting symbols to user apps
-        #define LAGRAPH_PUBLIC extern __declspec ( dllexport )
+        #define LAGRAPH_PUBLIC __declspec ( dllexport )
     #else
         // compiling the user application, importing symbols from LAGraph
-        #define LAGRAPH_PUBLIC extern __declspec ( dllimport )
+        #define LAGRAPH_PUBLIC __declspec ( dllimport )
     #endif
 #else
     // for other compilers
-    #define LAGRAPH_PUBLIC extern
+    #define LAGRAPH_PUBLIC
 #endif
 
 #if defined ( __cplusplus )
@@ -98,6 +98,9 @@
 
 #if ( !LAGRAPH_VANILLA ) && defined ( GxB_SUITESPARSE_GRAPHBLAS )
     // use SuiteSparse, and its GxB* extensions
+    #if GxB_IMPLEMENTATION < GxB_VERSION (7,1,0)
+    #error "If using SuiteSparse::GraphBLAS, version 7.1.0 or later is required"
+    #endif
     #define LAGRAPH_SUITESPARSE 1
 #else
     // use any GraphBLAS library (possibly SuiteSparse) but with no GxB*
@@ -367,6 +370,15 @@
     }                                           \
 }
 
+//==============================================================================
+// for C++ applications:
+//==============================================================================
+
+#if defined ( __cplusplus )
+extern "C"
+{
+#endif
+
 //==============================================================================
 // LAGraph memory management
 //==============================================================================
@@ -376,10 +388,10 @@
 // the following are pointers to the ANSI C11 malloc/calloc/realloc/free
 // functions.
 
-LAGRAPH_PUBLIC void * (* LAGraph_Malloc_function  ) (size_t)         ;
-LAGRAPH_PUBLIC void * (* LAGraph_Calloc_function  ) (size_t, size_t) ;
-LAGRAPH_PUBLIC void * (* LAGraph_Realloc_function ) (void *, size_t) ;
-LAGRAPH_PUBLIC void   (* LAGraph_Free_function    ) (void *)         ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Malloc_function  ) (size_t)         ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Calloc_function  ) (size_t, size_t) ;
+LAGRAPH_PUBLIC extern void * (* LAGraph_Realloc_function ) (void *, size_t) ;
+LAGRAPH_PUBLIC extern void   (* LAGraph_Free_function    ) (void *)         ;
 
 //------------------------------------------------------------------------------
 // LAGraph_Malloc:  allocate a block of memory (wrapper for malloc)
@@ -763,7 +775,7 @@ int LAGraph_Init
 // FUTURE: include these as built-in semirings in v2.1 C API, Table 3.9:
 
 // LAGraph semirings, created by LAGraph_Init or LAGr_Init:
-LAGRAPH_PUBLIC GrB_Semiring
+LAGRAPH_PUBLIC extern GrB_Semiring
 
     // LAGraph_plus_first_T: using the GrB_PLUS_MONOID_T monoid and the
     // corresponding GrB_FIRST_T multiplicative operator.
@@ -2503,4 +2515,8 @@ int LAGr_TriangleCount
     char *msg
 ) ;
 
+#if defined ( __cplusplus )
+}
+#endif
+
 #endif
diff --git a/include/LAGraphX.h b/include/LAGraphX.h
index 67d65876f5..6f453690c7 100644
--- a/include/LAGraphX.h
+++ b/include/LAGraphX.h
@@ -2,7 +2,7 @@
 // LAGraphX.h: include file for LAGraph experimental code
 //------------------------------------------------------------------------------
 
-// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 //
 // For additional details (including references to third party source code and
@@ -19,24 +19,46 @@
 #include <GraphBLAS.h>
 #include <LAGraph.h>
 
+#if ( _MSC_VER && !__INTEL_COMPILER && LGX_DLL )
+    #ifdef LGX_LIBRARY
+        // compiling LAGraph itself, exporting symbols to user apps
+        #define LAGRAPHX_PUBLIC __declspec ( dllexport )
+    #else
+        // compiling the user application, importing symbols from LAGraph
+        #define LAGRAPHX_PUBLIC __declspec ( dllimport )
+    #endif
+#else
+    // for other compilers
+    #define LAGRAPHX_PUBLIC
+#endif
+
+//==============================================================================
+// for C++ applications:
+//==============================================================================
+
+#if defined ( __cplusplus )
+extern "C"
+{
+#endif
+
 //==============================================================================
 // Experimental methods: in experimental/algorithm and experimental/utility
 //==============================================================================
 
 // Do not rely on these in production.  These methods are still under
-// development, and is intended only for illustration not benchmarking.  Do not
-// use for benchmarking, without asking the authors.
+// development, and is intended only for illustration or testing, not
+// benchmarking.  Do not use for benchmarking without asking the authors.
 
 //------------------------------------------------------------------------------
 // LAGraph_Random_*: Random number generator
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_Random_Init
 (
     char *msg
 ) ;
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_Random_Finalize
 (
     char *msg
@@ -44,10 +66,10 @@ int LAGraph_Random_Finalize
 
 #if defined ( COVERAGE )
 // for testing only
-LAGRAPH_PUBLIC bool random_hack ;
+LAGRAPHX_PUBLIC extern bool random_hack ;
 #endif
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_Random_Seed     // construct a random seed vector
 (
     // input/output
@@ -57,7 +79,7 @@ int LAGraph_Random_Seed     // construct a random seed vector
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_Random_Next     // advance to next random vector
 (
     // input/output
@@ -65,7 +87,7 @@ int LAGraph_Random_Next     // advance to next random vector
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_Random_Matrix    // random matrix of any built-in type
 (
     // output
@@ -151,7 +173,7 @@ typedef struct
 }
 LAGraph_Contents ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SWrite_HeaderStart  // write the first part of the JSON header
 (
     FILE *f,                    // file to write to
@@ -159,7 +181,7 @@ int LAGraph_SWrite_HeaderStart  // write the first part of the JSON header
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SWrite_HeaderItem   // write a single item to the JSON header
 (
     // inputs:
@@ -173,7 +195,7 @@ int LAGraph_SWrite_HeaderItem   // write a single item to the JSON header
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SWrite_HeaderItem   // write a single item to the JSON header
 (
     // inputs:
@@ -188,14 +210,14 @@ int LAGraph_SWrite_HeaderItem   // write a single item to the JSON header
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SWrite_HeaderEnd    // write the end of the JSON header
 (
     FILE *f,                    // file to write to
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SWrite_Item  // write the serialized blob of a matrix/vector/text
 (
     // input:
@@ -205,7 +227,7 @@ int LAGraph_SWrite_Item  // write the serialized blob of a matrix/vector/text
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SRead   // read a set of matrices from a *.lagraph file
 (
     FILE *f,                        // file to read from
@@ -216,7 +238,7 @@ int LAGraph_SRead   // read a set of matrices from a *.lagraph file
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 void LAGraph_SFreeContents      // free the Contents returned by LAGraph_SRead
 (
     // input/output
@@ -224,7 +246,7 @@ void LAGraph_SFreeContents      // free the Contents returned by LAGraph_SRead
     GrB_Index ncontents
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SSaveSet            // save a set of matrices from a *.lagraph file
 (
     // inputs:
@@ -252,7 +274,7 @@ int LAGraph_SLoadSet            // load a set of matrices from a *.lagraph file
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 void LAGraph_SFreeSet           // free a set of matrices
 (
     // input/output
@@ -280,7 +302,7 @@ void LAGraph_SFreeSet           // free a set of matrices
  * @retval GrB_SUCCESS      if completed successfully (equal or not)
  * @retval GrB_NULL_POINTER if kmax, ntris, nedges, nsteps is NULL
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_AllKTruss   // compute all k-trusses of a graph
 (
     // outputs
@@ -308,7 +330,7 @@ int LAGraph_AllKTruss   // compute all k-trusses of a graph
  * @retval GrB_NULL_POINTER if C or C_type is NULL
  * @return Any GraphBLAS errors that may have been encountered
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_KTruss      // compute the k-truss of a graph
 (
     // outputs:
@@ -335,7 +357,7 @@ int LAGraph_KTruss      // compute the k-truss of a graph
  * @retval GrB_SUCCESS      if completed successfully
  * @retval GrB_NULL_POINTER if result is NULL
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_cc_lacc (
     GrB_Vector *result,
     GrB_Matrix A,
@@ -360,7 +382,7 @@ int LAGraph_cc_lacc (
  * @retval GrB_INVALID_VALUE  if A is not square, s is not a valid vertex index
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_basic
 (
     GrB_Vector *pd_output,
@@ -383,7 +405,7 @@ GrB_Info LAGraph_BF_basic
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_basic_pushpull
 (
     GrB_Vector *pd_output,
@@ -406,7 +428,7 @@ GrB_Info LAGraph_BF_basic_pushpull
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_basic_mxv
 (
     GrB_Vector *pd_output,      //the pointer to the vector of distance
@@ -431,7 +453,7 @@ GrB_Info LAGraph_BF_basic_mxv
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_full
 (
     GrB_Vector *pd_output,
@@ -458,7 +480,7 @@ GrB_Info LAGraph_BF_full
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_full1
 (
     GrB_Vector *pd_output,
@@ -485,7 +507,7 @@ GrB_Info LAGraph_BF_full1
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_full1a
 (
     GrB_Vector *pd_output,
@@ -512,7 +534,7 @@ GrB_Info LAGraph_BF_full1a
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_full2
 (
     GrB_Vector *pd_output,      //the pointer to the vector of distance
@@ -539,7 +561,7 @@ GrB_Info LAGraph_BF_full2
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_full_mxv
 (
     GrB_Vector *pd_output,
@@ -560,18 +582,19 @@ GrB_Info LAGraph_BF_full_mxv
  * @param[in]   s        index of the source
  * @param[in]   n        number of nodes
  * @param[in]   nz       number of edges
- * @param[in]   I        row index vector (size n)
+ * @param[in]   Ilist    row index vector (size n)
  * @param[in]   J        column index vector (size nz)
- * @param[in]   W        weight vector (size nz), W(i) = weight of edge (I(i),J(i))
+ * @param[in]   W        weight vector (size nz), W(i) = weight of edge 
+ *                       (Ilist(i),J(i))
  *
  * @retval GrB_SUCCESS        if completed successfully
- * @retval GrB_NULL_POINTER   If pd, ppi, I, J, or W is NULL
+ * @retval GrB_NULL_POINTER   If pd, ppi, Ilist, J, or W is NULL
  * @retval GrB_INVALID_VALUE  if s is not a valid vertex index
  * @retval GrB_OUT_OF_MEMORY  if allocation fails.
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_pure_c
 (
     int32_t **pd,
@@ -581,7 +604,7 @@ GrB_Info LAGraph_BF_pure_c
     const int64_t s,
     const int64_t n,
     const int64_t nz,
-    const int64_t *I,
+    const int64_t *Ilist,
     const int64_t *J,
     const int32_t *W
 ) ;
@@ -597,18 +620,19 @@ GrB_Info LAGraph_BF_pure_c
  * @param[in]   s        index of the source
  * @param[in]   n        number of nodes
  * @param[in]   nz       number of edges
- * @param[in]   I        row index vector (size n)
+ * @param[in]   Ilist    row index vector (size n)
  * @param[in]   J        column index vector (size nz)
- * @param[in]   W        weight vector (size nz), W(i) = weight of edge (I(i),J(i))
+ * @param[in]   W        weight vector (size nz), W(i) = weight of edge
+ *                       (Ilist(i),J(i))
  *
  * @retval GrB_SUCCESS        if completed successfully
- * @retval GrB_NULL_POINTER   If pd, ppi, I, J, or W is NULL
+ * @retval GrB_NULL_POINTER   If pd, ppi, Ilist, J, or W is NULL
  * @retval GrB_INVALID_VALUE  if s is not a valid vertex index
  * @retval GrB_OUT_OF_MEMORY  if allocation fails.
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  *
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_BF_pure_c_double
 (
     double **pd,
@@ -618,7 +642,7 @@ GrB_Info LAGraph_BF_pure_c_double
     const int64_t s,
     const int64_t n,
     const int64_t nz,
-    const int64_t *I,
+    const int64_t *Ilist,
     const int64_t *J,
     const double  *W
 ) ;
@@ -642,7 +666,7 @@ GrB_Info LAGraph_BF_pure_c_double
  * @retval GrB_OUT_OF_MEMORY  if allocation fails.
  * @retval GrB_NO_VALUE       if A has a negative weight cycle
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_cdlp
 (
     GrB_Vector *CDLP_handle,
@@ -671,7 +695,7 @@ int LAGraph_cdlp
  * @retval GrB_DOMAIN_MISMATCH if type of Y0 is not FP32 or FP64, or the types of
  *                             W or Bias arent the same as Y0
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_dnn
 (
     // output
@@ -696,7 +720,7 @@ GrB_Info LAGraph_dnn
  * @retval GrB_NULL_POINTER    If D or D_type is NULL
  * @retval GrB_INVALID_VALUE   If G is not square
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 GrB_Info LAGraph_FW
 (
     const GrB_Matrix G,
@@ -721,7 +745,7 @@ GrB_Info LAGraph_FW
  * @retval GrB_NULL_POINTER   If LCC_handle or LCC_type is NULL
  * @retval GrB_INVALID_VALUE  If A is not stored in CSR format
  */
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_lcc            // compute lcc for all nodes in A
 (
     GrB_Vector *LCC_handle,     // output vector
@@ -735,7 +759,7 @@ int LAGraph_lcc            // compute lcc for all nodes in A
 
 //****************************************************************************
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_msf
 (
     GrB_Matrix *result, // output: an unsymmetrical matrix, the spanning forest
@@ -746,7 +770,7 @@ int LAGraph_msf
 
 //****************************************************************************
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_scc (
     GrB_Vector *result,     // output: array of component identifiers
     GrB_Matrix A,           // input matrix
@@ -754,7 +778,7 @@ int LAGraph_scc (
 ) ;
 
 //****************************************************************************
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_VertexCentrality_Triangle       // vertex triangle-centrality
 (
     // outputs:
@@ -767,7 +791,7 @@ int LAGraph_VertexCentrality_Triangle       // vertex triangle-centrality
 ) ;
 
 //****************************************************************************
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_MaximalIndependentSet       // maximal independent set
 (
     // outputs:
@@ -782,7 +806,7 @@ int LAGraph_MaximalIndependentSet       // maximal independent set
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
 (
     // output
@@ -796,7 +820,7 @@ int LG_CC_FastSV5           // SuiteSparse:GraphBLAS method, with GxB extensions
 // kcore algorithms
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_KCore_All
 (
     // outputs:
@@ -807,7 +831,7 @@ int LAGraph_KCore_All
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_KCore
 (
     // outputs:
@@ -818,7 +842,7 @@ int LAGraph_KCore
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_KCore_Decompose
 (
     // outputs:
@@ -834,7 +858,7 @@ int LAGraph_KCore_Decompose
 // counting graphlets
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_FastGraphletTransform
 (
     // outputs:
@@ -845,7 +869,7 @@ int LAGraph_FastGraphletTransform
     char *msg
 ) ;
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_SquareClustering
 (
     // outputs:
@@ -859,7 +883,7 @@ int LAGraph_SquareClustering
 // a simple example of an algorithm
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LAGRAPHX_PUBLIC
 int LAGraph_HelloWorld // a simple algorithm, just for illustration
 (
     // output
@@ -869,4 +893,8 @@ int LAGraph_HelloWorld // a simple algorithm, just for illustration
     char *msg
 ) ;
 
+#if defined ( __cplusplus )
+}
+#endif
+
 #endif
diff --git a/rtdocs/CMakeLists.txt b/rtdocs/CMakeLists.txt
index 10c0f9e30e..5b06879b7c 100644
--- a/rtdocs/CMakeLists.txt
+++ b/rtdocs/CMakeLists.txt
@@ -27,7 +27,9 @@ set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
 set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
 
 # Set the Doxygen input and output directories in the Doxyfile
-configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
+configure_file ( ${DOXYFILE_IN} ${DOXYFILE_OUT}
+    @ONLY
+    NEWLINE_STYLE LF )
 
 # Doxygen won't create this for us
 file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR})
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index daa435fbb4..515103d6b9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,7 +2,7 @@
 # LAGraph/src/CMakeLists.txt:  cmake script for LAGraph/src
 #-------------------------------------------------------------------------------
 
-# LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+# LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 # SPDX-License-Identifier: BSD-2-Clause
 #
 # For additional details (including references to third party source code and
@@ -13,11 +13,11 @@
 
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/include utility )
+include_directories ( utility )
 
 file ( GLOB LAGRAPH_LIB_SOURCES "utility/*.c" "algorithm/*.c" )
 
-if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" )
+if ( WIN32 )
     set ( M_LIB "" )
 else ( )
     set ( M_LIB "m" )
@@ -27,52 +27,84 @@ endif ( )
 # dynamic lagraph library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraph SHARED ${LAGRAPH_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraph PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11
-    PUBLIC_HEADER "include/LAGraph.h" )
-set_property ( TARGET lagraph PROPERTY C_STANDARD 11 )
-target_link_libraries ( lagraph PUBLIC ${GRAPHBLAS_LIBRARIES} ${M_LIB} )
-target_link_directories ( lagraph BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-target_include_directories ( lagraph PUBLIC include/ )
-# install ( FILES ${LAGRAPH_INCLUDE} DESTINATION include)
+if ( BUILD_SHARED_LIBS )
+    add_library ( LAGraph SHARED ${LAGRAPH_LIB_SOURCES} )
+    set_target_properties ( LAGraph PROPERTIES
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        OUTPUT_NAME lagraph
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        PUBLIC_HEADER "include/LAGraph.h"
+        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/dlls )
+
+    if ( ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.25" )
+        set_target_properties ( LAGraph PROPERTIES EXPORT_NO_SYSTEM ON )
+    endif ( )
+
+    target_link_libraries ( LAGraph PRIVATE GraphBLAS::GraphBLAS ${M_LIB} )
+
+    target_include_directories ( LAGraph PUBLIC
+        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+        $<INSTALL_INTERFACE:${SUITESPARSE_INCLUDEDIR}> )
+
+    target_compile_definitions ( LAGraph PRIVATE LG_LIBRARY )
+    target_compile_definitions ( LAGraph PUBLIC LG_DLL )
+    # install ( FILES ${LAGRAPH_INCLUDE} DESTINATION include)
+endif ( )
 
 #-------------------------------------------------------------------------------
 # static lagraph library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraph_static STATIC ${LAGRAPH_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraph_static PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    OUTPUT_NAME lagraph
-    POSITION_INDEPENDENT_CODE OFF
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-
-if ( MSVC )
-    set_target_properties ( lagraph_static PROPERTIES
-        OUTPUT_NAME lagraph_static )
+if ( BUILD_STATIC_LIBS )
+    add_library ( LAGraph_static STATIC ${LAGRAPH_LIB_SOURCES} )
+    SET_TARGET_PROPERTIES ( LAGraph_static PROPERTIES
+        OUTPUT_NAME lagraph
+        POSITION_INDEPENDENT_CODE OFF
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        PUBLIC_HEADER "include/LAGraph.h" )
+
+    if ( MSVC )
+        set_target_properties ( LAGraph_static PROPERTIES
+            OUTPUT_NAME lagraph_static )
+    endif ( )
+
+    if ( ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.25" )
+        set_target_properties ( LAGraph_static PROPERTIES EXPORT_NO_SYSTEM ON )
+    endif ( )
+
+    if ( TARGET GraphBLAS::GraphBLAS_static )
+        target_link_libraries ( LAGraph_static PUBLIC GraphBLAS::GraphBLAS_static )
+    else ( )
+        target_link_libraries ( LAGraph_static PUBLIC GraphBLAS::GraphBLAS )
+    endif ( )
+    target_link_libraries ( LAGraph_static PUBLIC ${M_LIB} )
+
+    target_include_directories ( LAGraph_static PUBLIC
+        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+        $<INSTALL_INTERFACE:${SUITESPARSE_INCLUDEDIR}> )
 endif ( )
 
-set_property ( TARGET lagraph_static PROPERTY C_STANDARD 11 )
-target_link_libraries ( lagraph_static PUBLIC ${GRAPHBLAS_LIBRARIES} ${M_LIB} )
-target_link_directories( lagraph_static BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-
 #-------------------------------------------------------------------------------
 # add OpenMP
 #-------------------------------------------------------------------------------
 
-if ( OPENMP_FOUND )
-    target_link_libraries ( lagraph PUBLIC ${OpenMP_C_LIBRARIES} )
-    target_link_libraries ( lagraph_static PUBLIC ${OpenMP_C_LIBRARIES} )
+if ( OpenMP_C_FOUND )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries ( LAGraph PRIVATE OpenMP::OpenMP_C )
+    endif ( )
+    if ( BUILD_STATIC_LIBS )
+        target_link_libraries ( LAGraph_static PRIVATE OpenMP::OpenMP_C )
+    endif ( )
 endif ( )
 
 #-------------------------------------------------------------------------------
 # applications
 #-------------------------------------------------------------------------------
 
-add_subdirectory ( test )
-add_subdirectory ( benchmark )
-
+if ( BUILD_TESTING )
+    add_subdirectory ( test )
+    add_subdirectory ( benchmark )
+endif ( )
diff --git a/src/algorithm/LG_CC_Boruvka.c b/src/algorithm/LG_CC_Boruvka.c
index 79cc5a3dd0..3c6998185a 100644
--- a/src/algorithm/LG_CC_Boruvka.c
+++ b/src/algorithm/LG_CC_Boruvka.c
@@ -25,6 +25,8 @@
 // slower in general than LG_CC_FastSV6, which uses GxB pack/unpack methods
 // for faster access to the contents of the matrices and vectors.
 
+#include <stdint.h>
+
 #include "LG_internal.h"
 
 //------------------------------------------------------------------------------
@@ -65,14 +67,20 @@ static GrB_Info Reduce_assign
 // select_func: IndexUnaryOp for pruning entries from S
 //------------------------------------------------------------------------------
 
-// Rather than using a global variable to access the Px array, it is passed to
-// the select function as a uint64_t value that contains a pointer to Px.  It
-// might be better to create a user-defined type for y, but this works fine.
+// The pointer to the Px array is passed to the select function as a component
+// of a user-defined data type.
+
+typedef struct
+{
+    GrB_Index *pointer ;
+}
+Parent_struct ;
 
 void my_select_func (void *z, const void *x,
                  const GrB_Index i, const GrB_Index j, const void *y)
 {
-    GrB_Index *Px = (*(GrB_Index **) y) ;
+    Parent_struct *Parent = (Parent_struct *) y ;
+    GrB_Index *Px = Parent->pointer ;
     (*((bool *) z)) = (Px [i] != Px [j]) ;
 }
 
@@ -93,6 +101,8 @@ void my_select_func (void *z, const void *x,
     LAGraph_Free ((void **) &I, NULL) ;     \
     LAGraph_Free ((void **) &Px, NULL) ;    \
     LAGraph_Free ((void **) &mem, NULL) ;   \
+    GrB_free (&S) ;                         \
+    GrB_free (&Parent_Type) ;               \
     GrB_free (&gp) ;                        \
     GrB_free (&mnp) ;                       \
     GrB_free (&ccmn) ;                      \
@@ -120,6 +130,8 @@ int LG_CC_Boruvka
         mask = NULL ;
     GrB_IndexUnaryOp select_op = NULL ;
     GrB_Matrix S = NULL ;
+    GrB_Type Parent_Type = NULL ;
+    Parent_struct Parent ;
 
     LG_CLEAR_MSG ;
     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
@@ -147,6 +159,9 @@ int LG_CC_Boruvka
 
     LG_TRY (LAGraph_Malloc ((void **) &mem, 3*n, sizeof (GrB_Index), msg)) ;
     LG_TRY (LAGraph_Malloc ((void **) &Px, n, sizeof (GrB_Index), msg)) ;
+    Parent.pointer = Px ;
+
+    GRB_TRY (GrB_Type_new (&Parent_Type, sizeof (Parent_struct))) ;
 
     #if !LAGRAPH_SUITESPARSE
     // I is not needed for SuiteSparse and remains NULL
@@ -163,7 +178,7 @@ int LG_CC_Boruvka
     GRB_TRY (GrB_Vector_extractTuples (I, Px, &n, parent)) ;
 
     GRB_TRY (GrB_IndexUnaryOp_new (&select_op, my_select_func, GrB_BOOL,
-        /* aij: ignored */ GrB_BOOL, /* y: pointer to Px */ GrB_UINT64)) ;
+        /* aij: ignored */ GrB_BOOL, /* y: pointer to Px */ Parent_Type)) ;
 
     GrB_Index nvals ;
     GRB_TRY (GrB_Matrix_nvals (&nvals, S)) ;
@@ -249,7 +264,8 @@ int LG_CC_Boruvka
 
         // This step is the costliest part of this algorithm when dealing with
         // large matrices.
-        GRB_TRY (GrB_select (S, NULL, NULL, select_op, S, (uint64_t) Px, NULL));
+        GRB_TRY (GrB_Matrix_select_UDT (S, NULL, NULL, select_op, S,
+            (void *) (&Parent), NULL)) ;
         GRB_TRY (GrB_Matrix_nvals (&nvals, S)) ;
     }
 
@@ -261,3 +277,4 @@ int LG_CC_Boruvka
     LG_FREE_WORK ;
     return (GrB_SUCCESS) ;
 }
+
diff --git a/src/algorithm/LG_CC_FastSV6.c b/src/algorithm/LG_CC_FastSV6.c
index 2a8043a851..24b9001416 100644
--- a/src/algorithm/LG_CC_FastSV6.c
+++ b/src/algorithm/LG_CC_FastSV6.c
@@ -47,6 +47,9 @@
 // G->A will then become a truly read-only object (assuming GrB_wait (G->A)
 // has been done first).
 
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+
 #define LG_FREE_ALL ;
 #include "LG_internal.h"
 
@@ -230,6 +233,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
 
     LG_TRY (LAGraph_CheckGraph (G, msg)) ;
     LG_ASSERT (component != NULL, GrB_NULL_POINTER) ;
+    (*component) = NULL ;
 
     LG_ASSERT_MSG ((G->kind == LAGraph_ADJACENCY_UNDIRECTED ||
        (G->kind == LAGraph_ADJACENCY_DIRECTED &&
@@ -408,7 +412,8 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         //----------------------------------------------------------------------
 
         // thread tid works on rows range[tid]:range[tid+1]-1 of A and T
-        for (int tid = 0 ; tid <= nthreads ; tid++)
+        int tid;
+        for (tid = 0 ; tid <= nthreads ; tid++)
         {
             range [tid] = (n * tid + nthreads - 1) / nthreads ;
         }
@@ -418,7 +423,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         //----------------------------------------------------------------------
 
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             for (int64_t i = range [tid] ; i < range [tid+1] ; i++)
             {
@@ -431,7 +436,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         // count = cumsum (count)
         //----------------------------------------------------------------------
 
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             count [tid + 1] += count [tid] ;
         }
@@ -443,7 +448,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         // T (i,:) consists of the first FASTSV_SAMPLES of A (i,:).
 
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index p = count [tid] ;
             Tp [range [tid]] = p ;
@@ -473,7 +478,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         // find the connected components of T
         //----------------------------------------------------------------------
 
-        GRB_TRY (fastsv (T, parent, mngp, &gp, &gp_new, t, eq, min, min_2nd,
+        LG_TRY (fastsv (T, parent, mngp, &gp, &gp_new, t, eq, min, min_2nd,
             C, &Cp, &Px, &Cx, msg)) ;
 
         //----------------------------------------------------------------------
@@ -551,9 +556,8 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
         bool T_jumbled, T_iso ;
         GRB_TRY (GxB_Matrix_unpack_CSR (T, &Tp, &Tj, &Tx, &Tp_size, &Tj_size,
             &Tx_size, &T_iso, &T_jumbled, NULL)) ;
-
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index p = Ap [range [tid]] ;
             // thread tid scans A (range [tid]:range [tid+1]-1,:),
@@ -598,17 +602,17 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
 
         // Compact empty space out of Tj not filled in from the above phase.
         nvals = 0 ;
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
-            memcpy (Tj + nvals, Tj + Tp [range [tid]],
-                sizeof (GrB_Index) * count [tid]) ;
+            memmove (Tj + nvals,
+                Tj + Tp [range [tid]], sizeof (GrB_Index) * count [tid]) ;
             nvals += count [tid] ;
             count [tid] = nvals - count [tid] ;
         }
 
         // Compact empty space out of Tp
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int tid = 0 ; tid < nthreads ; tid++)
+        for (tid = 0 ; tid < nthreads ; tid++)
         {
             GrB_Index p = Tp [range [tid]] ;
             for (int64_t i = range [tid] ; i < range [tid+1] ; i++)
@@ -653,7 +657,7 @@ int LG_CC_FastSV6           // SuiteSparse:GraphBLAS method, with GxB extensions
     // final phase
     //--------------------------------------------------------------------------
 
-    GRB_TRY (fastsv (A, parent, mngp, &gp, &gp_new, t, eq, min, min_2nd,
+    LG_TRY (fastsv (A, parent, mngp, &gp, &gp_new, t, eq, min, min_2nd,
         C, &Cp, &Px, &Cx, msg)) ;
 
     //--------------------------------------------------------------------------
diff --git a/src/benchmark/CMakeLists.txt b/src/benchmark/CMakeLists.txt
index ac1cebe34c..4025d37475 100644
--- a/src/benchmark/CMakeLists.txt
+++ b/src/benchmark/CMakeLists.txt
@@ -13,8 +13,8 @@
 
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/src/test/include
-    ${CMAKE_SOURCE_DIR}/src/algorithm )
+include_directories ( ${PROJECT_SOURCE_DIR}/src/test/include
+    ${PROJECT_SOURCE_DIR}/src/algorithm )
 
 file( GLOB DEMO_SOURCES LIST_DIRECTORIES false *_demo.c )
 foreach( demosourcefile ${DEMO_SOURCES} )
@@ -22,6 +22,12 @@ foreach( demosourcefile ${DEMO_SOURCES} )
     string( REPLACE ".c" "" demoname ${justname} )
 #   message("Adding: ${demoname}")
     add_executable( ${demoname} ${demosourcefile} )
-    target_link_libraries( ${demoname} lagraph lagraphx lagraphtest ${GRAPHBLAS_LIBRARIES} )
-    target_link_directories( ${demoname} BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+    set_target_properties ( ${demoname} PROPERTIES
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries( ${demoname} LAGraph LAGraphX lagraphtest GraphBLAS::GraphBLAS )
+    else ( )
+        target_link_libraries( ${demoname} LAGraph_static LAGraphX_static lagraphtest_static GraphBLAS::GraphBLAS )
+    endif ( )
 endforeach( demosourcefile ${DEMO_SOURCES} )
diff --git a/src/benchmark/README.md b/src/benchmark/README.md
index 1bb6b89383..9789c69e3b 100644
--- a/src/benchmark/README.md
+++ b/src/benchmark/README.md
@@ -1,7 +1,7 @@
 # LAGraph/src/benchmark:  Demo programs that use LAGraph and GraphBLAS
 # to run all of the GAP Benchmark problems.
 
-LAGraph, (c) 2021-2022 by The LAGraph Contributors, All Rights Reserved.
+LAGraph, (c) 2021-2023 by The LAGraph Contributors, All Rights Reserved.
 SPDX-License-Identifier: BSD-2-Clause
 See additional acknowledgments in the LICENSE file,
 or contact permission@sei.cmu.edu for the full terms.
@@ -14,19 +14,12 @@ impact on performance.  Also, please contact the authors of the library if you
 have any questions about benchmarking.  (Tim Davis: davis@tamu.edu, in
 particular).
 
-LAGraph is a draft package (not yet v1.0), and its performance is not yet
-stable.  It includes many draft algorithms that are sometimes posted on github
-in debug mode, or with known suboptimal performance.  We ask that you not
-benchmark LAGraph on your own without contacting the authors to make sure you
-have the right version, and the right version of SuiteSparse:GraphBLAS to go
-with it.
-
 If you run in vanilla mode, by compiling LAGraph with
 
     cmake -DLAGRAPH_VANILLA=1 ..
 
 Then performance can be quite low since in this case LAGraph does not use
-any SuiteSparse:GraphBLAS GxB extensions.  We are still developing the
+any SuiteSparse:GraphBLAS extensions.  We are still developing the
 pure GrB implementations of these algorithms.
 
 However, assuming things are stable, follow the instructions in the
diff --git a/src/benchmark/bc_demo.c b/src/benchmark/bc_demo.c
index 76a1b1bdc8..1d606544dd 100644
--- a/src/benchmark/bc_demo.c
+++ b/src/benchmark/bc_demo.c
@@ -53,6 +53,8 @@
     GrB_free (&SourceNodes) ;       \
 }
 
+#define BATCH_SIZE 4
+
 int main (int argc, char **argv)
 {
 
@@ -66,7 +68,7 @@ int main (int argc, char **argv)
     bool burble = false ;
     demo_init (burble) ;
 
-    int batch_size = 4 ;
+    int batch_size = BATCH_SIZE ;
 
     //--------------------------------------------------------------------------
     // determine # of threads to use
@@ -96,8 +98,7 @@ int main (int argc, char **argv)
     }
     printf ("\n") ;
 
-    double tt [nthreads_max+1] ;
-    double tt2 [nthreads_max+1] ;
+    double *tt = malloc ((nthreads_max+1) *sizeof (double));
 
     //--------------------------------------------------------------------------
     // read in the graph
@@ -138,7 +139,7 @@ int main (int argc, char **argv)
 
         ntrials++ ;
         printf ("\nTrial %d : sources: [", ntrials) ;
-        GrB_Index vertex_list [batch_size] ;
+        GrB_Index vertex_list [BATCH_SIZE] ;
         for (int64_t k = 0 ; k < batch_size ; k++)
         {
             // get the kth source node
@@ -147,8 +148,8 @@ int main (int argc, char **argv)
                 k + kstart, 0)) ;
             // subtract one to convert from 1-based to 0-based
             source-- ;
-            vertex_list [k] = source  ;
-            printf (" %"PRIu64, source) ;
+            vertex_list [k] = source ;
+            printf (" %"PRId64, source) ;
         }
         printf (" ]\n") ;
 
@@ -197,6 +198,7 @@ int main (int argc, char **argv)
             Nthreads [t], t2, matrix_name) ;
     }
 
+    free ((void *) tt);
     LG_FREE_ALL;
     LAGRAPH_TRY (LAGraph_Finalize (msg)) ;
     return (GrB_SUCCESS) ;
diff --git a/src/benchmark/bfs_demo.c b/src/benchmark/bfs_demo.c
index 5b198fcbcd..6042418205 100644
--- a/src/benchmark/bfs_demo.c
+++ b/src/benchmark/bfs_demo.c
@@ -81,9 +81,9 @@ int main (int argc, char **argv)
     }
     printf ("\n") ;
 
-    double tpl [nthreads_max+1] ;
-    double tp [nthreads_max+1] ;
-    double tl [nthreads_max+1] ;
+    double *tpl = malloc ((nthreads_max+1) * sizeof (double)) ;
+    double *tp = malloc ((nthreads_max+1) * sizeof (double)) ;
+    double *tl = malloc ((nthreads_max+1) * sizeof (double)) ;
 
     //--------------------------------------------------------------------------
     // read in the graph
@@ -295,6 +295,9 @@ int main (int argc, char **argv)
     // free all workspace and finish
     //--------------------------------------------------------------------------
 
+    free ((void *) tpl) ;
+    free ((void *) tp) ;
+    free ((void *) tl) ;
     LG_FREE_ALL ;
     LAGRAPH_TRY (LAGraph_Finalize (msg)) ;
     return (GrB_SUCCESS) ;
diff --git a/src/benchmark/cc_demo.c b/src/benchmark/cc_demo.c
index 7974615aac..42a0930db3 100644
--- a/src/benchmark/cc_demo.c
+++ b/src/benchmark/cc_demo.c
@@ -101,8 +101,6 @@ int main (int argc, char **argv)
     }
     printf ("\n") ;
 
-    double tt [nthreads_max+1] ;
-
     //--------------------------------------------------------------------------
     // read in the graph
     //--------------------------------------------------------------------------
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index ac675e0328..025b1b35ab 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -20,8 +20,8 @@
 # build the lagraphtest library
 #-------------------------------------------------------------------------------
 
-include_directories ( ${CMAKE_SOURCE_DIR}/src/test/include
-    ${CMAKE_SOURCE_DIR}/src/algorithm )
+include_directories ( ${PROJECT_SOURCE_DIR}/src/test/include
+    ${PROJECT_SOURCE_DIR}/src/algorithm )
 
 file ( GLOB LAGRAPHTEST_LIB_SOURCES "LG_*.c" )
 
@@ -37,43 +37,52 @@ endif ( )
 # dynamic lagraphtest library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphtest SHARED ${LAGRAPHTEST_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphtest PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-set_property ( TARGET lagraphtest PROPERTY C_STANDARD 11 )
-target_link_libraries( lagraphtest PUBLIC lagraph ${GRAPHBLAS_LIBRARIES})
-target_link_directories( lagraphtest BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
+if ( BUILD_SHARED_LIBS )
+    add_library ( lagraphtest SHARED ${LAGRAPHTEST_LIB_SOURCES} )
+    set_target_properties ( lagraphtest PROPERTIES
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11
+        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/dlls )
+    target_link_libraries ( lagraphtest PRIVATE LAGraph GraphBLAS::GraphBLAS )
+    target_compile_definitions ( lagraphtest PRIVATE LG_TEST_LIBRARY )
+    target_compile_definitions ( lagraphtest PUBLIC LG_TEST_DLL )
+endif ( )
 
 #-------------------------------------------------------------------------------
 # static lagraphtest library properties
 #-------------------------------------------------------------------------------
 
-add_library ( lagraphtest_static STATIC ${LAGRAPHTEST_LIB_SOURCES} )
-SET_TARGET_PROPERTIES ( lagraphtest_static PROPERTIES
-    VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
-    OUTPUT_NAME lagraphtest
-    POSITION_INDEPENDENT_CODE OFF
-    SOVERSION ${LAGraph_VERSION_MAJOR}
-    C_STANDARD_REQUIRED 11 )
-
-if ( MSVC )
+if ( BUILD_STATIC_LIBS )
+    add_library ( lagraphtest_static STATIC ${LAGRAPHTEST_LIB_SOURCES} )
     set_target_properties ( lagraphtest_static PROPERTIES
-        OUTPUT_NAME lagraphtest_static )
+        VERSION ${LAGraph_VERSION_MAJOR}.${LAGraph_VERSION_MINOR}.${LAGraph_VERSION_SUB}
+        OUTPUT_NAME lagraphtest
+        POSITION_INDEPENDENT_CODE OFF
+        SOVERSION ${LAGraph_VERSION_MAJOR}
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+
+    if ( MSVC )
+        set_target_properties ( lagraphtest_static PROPERTIES
+            OUTPUT_NAME lagraphtest_static )
+    endif ( )
+
+    target_link_libraries ( lagraphtest_static PRIVATE LAGraph_static GraphBLAS::GraphBLAS )
 endif ( )
 
-set_property ( TARGET lagraphtest_static PROPERTY C_STANDARD 11 )
-target_link_libraries(lagraphtest_static PUBLIC lagraph ${GRAPHBLAS_LIBRARIES})
-target_link_directories( lagraphtest_static BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-
 #-------------------------------------------------------------------------------
 # add OpenMP
 #-------------------------------------------------------------------------------
 
-if ( OPENMP_FOUND )
-    target_link_libraries ( lagraphtest PUBLIC ${OpenMP_C_LIBRARIES} )
-    target_link_libraries ( lagraphtest_static PUBLIC ${OpenMP_C_LIBRARIES} )
+if ( OpenMP_C_FOUND )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries ( lagraphtest PRIVATE OpenMP::OpenMP_C )
+    endif ( )
+    if ( BUILD_STATIC_LIBS )
+        target_link_libraries ( lagraphtest_static PRIVATE OpenMP::OpenMP_C )
+    endif ( )
 endif ( )
 
 #-------------------------------------------------------------------------------
@@ -86,9 +95,25 @@ foreach( testsourcefile ${TEST_SOURCES} )
     string( REPLACE ".c" "" testname ${justname} )
 #   message("Adding: ${testname}")
     add_executable( ${testname} ${testsourcefile})
-    target_link_libraries( ${testname} lagraph lagraphx lagraphtest ${GRAPHBLAS_LIBRARIES} )
-    target_link_directories( ${testname} BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/build )
-    string( REPLACE "test_" "ctest_" ctestname ${testname})
-    add_test( ${ctestname} ${testname})
+    set_target_properties ( ${testname} PROPERTIES
+        C_STANDARD_REQUIRED ON
+        C_STANDARD 11 )
+    if ( BUILD_SHARED_LIBS )
+        target_link_libraries( ${testname} LAGraph LAGraphX lagraphtest GraphBLAS::GraphBLAS )
+    else ( )
+        target_link_libraries( ${testname} LAGraph_static LAGraphX_static lagraphtest_static GraphBLAS::GraphBLAS )
+    endif ( )
+    string( REPLACE "test_" "LAGraph_" ctestname ${testname})
+    add_test( NAME ${ctestname} COMMAND $<TARGET_FILE:${testname}> )
+#   add_test( NAME ${ctestname} COMMAND valgrind $<TARGET_FILE:${testname}> )
+    if (WIN32)
+        if ( BUILD_SHARED_LIBS )
+            set_tests_properties ( ${ctestname} PROPERTIES
+                ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:GraphBLAS::GraphBLAS>;PATH=path_list_prepend:$<TARGET_FILE_DIR:lagraphtest>" )
+        else ( )
+            set_tests_properties ( ${ctestname} PROPERTIES
+                ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:GraphBLAS::GraphBLAS>" )
+        endif ( )
+    endif ( )
 endforeach( testsourcefile ${TEST_SOURCES} )
 
diff --git a/src/test/LG_brutal_malloc.c b/src/test/LG_brutal_malloc.c
index 6db6373ef6..1af8e12cf4 100644
--- a/src/test/LG_brutal_malloc.c
+++ b/src/test/LG_brutal_malloc.c
@@ -19,6 +19,7 @@
 // LAGr_Init.
 
 #include "LG_internal.h"
+#include "LG_test.h"
 
 //------------------------------------------------------------------------------
 // global variables: LG_brutal and LG_nmalloc
@@ -38,14 +39,14 @@
 // It is decremented by LG_brutal_free.  After LAGraph_Finalize is called,
 // this value should be zero.  If nonzero, a memory leak has occured.
 
-int64_t LG_brutal = -1 ;
-int64_t LG_nmalloc = 0 ;
+LG_TEST_PUBLIC int64_t LG_brutal = -1 ;
+LG_TEST_PUBLIC int64_t LG_nmalloc = 0 ;
 
 //------------------------------------------------------------------------------
 // LG_brutal_malloc
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_malloc      // return pointer to allocated block of memory
 (
     size_t size             // # of bytes to allocate
@@ -83,7 +84,7 @@ void *LG_brutal_malloc      // return pointer to allocated block of memory
 // LG_brutal_calloc
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_calloc      // return pointer to allocated block of memory
 (
     size_t nitems,          // # of items to allocate
@@ -103,7 +104,7 @@ void *LG_brutal_calloc      // return pointer to allocated block of memory
 // LG_brutal_free
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void LG_brutal_free
 (
     void *p                 // block to free
@@ -125,7 +126,7 @@ void LG_brutal_free
 // LG_brutal_realloc
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_realloc     // return pointer to reallocated memory
 (
     void *p,                // block to realloc
diff --git a/src/test/LG_check_sssp.c b/src/test/LG_check_sssp.c
index 4d0a20fc4a..204775c602 100644
--- a/src/test/LG_check_sssp.c
+++ b/src/test/LG_check_sssp.c
@@ -102,25 +102,25 @@ int LG_check_sssp
     {
         etypecode = 0 ;
         etypesize = sizeof (int32_t) ;
-        etypeinf  = INT32_MAX ;
+        etypeinf  = (double) INT32_MAX ;
     }
     else if (etype == GrB_INT64)
     {
         etypecode = 1 ;
         etypesize = sizeof (int64_t) ;
-        etypeinf  = INT64_MAX ;
+        etypeinf  = (double) INT64_MAX ;
     }
     else if (etype == GrB_UINT32)
     {
         etypecode = 2 ;
         etypesize = sizeof (uint32_t) ;
-        etypeinf  = UINT32_MAX ;
+        etypeinf  = (double) UINT32_MAX ;
     }
     else if (etype == GrB_UINT64)
     {
         etypecode = 3 ;
         etypesize = sizeof (uint64_t) ;
-        etypeinf  = UINT64_MAX ;
+        etypeinf  = (double) UINT64_MAX ;
     }
     else if (etype == GrB_FP32)
     {
@@ -251,7 +251,7 @@ int LG_check_sssp
         // directly access the indices of entries in A(u,:)
         GrB_Index degree = Ap [u+1] - Ap [u] ;
         GrB_Index *node_u_adjacency_list = Aj + Ap [u] ;
-        void *weights = Ax + ((iso ? 0 : Ap [u]) * etypesize) ;
+        void *weights = ((char *) Ax) + ((iso ? 0 : Ap [u]) * etypesize) ;
         #else
         // extract the indices of entries in A(u,:)
         GrB_Index degree = n ;
diff --git a/src/test/LG_check_tri.c b/src/test/LG_check_tri.c
index 59fbff8983..9b8e426030 100644
--- a/src/test/LG_check_tri.c
+++ b/src/test/LG_check_tri.c
@@ -85,10 +85,11 @@ int LG_check_tri        // -1 if out of memory, 0 if successful
     Ai = Aj ;       // pretend A is symmetric and in CSC format instead
 
     // masked dot-product method
+    int64_t j;
     #if !defined ( COVERAGE )
     #pragma omp parallel for reduction(+:ntriangles) schedule(dynamic,1024)
     #endif
-    for (int64_t j = 0 ; j < n ; j++)
+    for (j = 0 ; j < n ; j++)
     {
         // for each entry in the lower triangular part of A
         for (int64_t p = Ap [j] ; p < Ap [j+1] ; p++)
diff --git a/src/test/include/LG_test.h b/src/test/include/LG_test.h
index 337934596a..056896edf1 100644
--- a/src/test/include/LG_test.h
+++ b/src/test/include/LG_test.h
@@ -16,6 +16,20 @@
 
 #include <GraphBLAS.h>
 #include <LAGraph.h>
+#undef I
+
+#if ( _MSC_VER && !__INTEL_COMPILER && LG_TEST_DLL )
+    #ifdef LG_TEST_LIBRARY
+        // compiling LAGraph itself, exporting symbols to user apps
+        #define LG_TEST_PUBLIC __declspec ( dllexport )
+    #else
+        // compiling the user application, importing symbols from LAGraph
+        #define LG_TEST_PUBLIC __declspec ( dllimport )
+    #endif
+#else
+    // for other compilers
+    #define LG_TEST_PUBLIC
+#endif
 
 int LG_check_bfs
 (
@@ -133,32 +147,32 @@ int LG_check_export
 //      all entries cleared, if an out-of-memory failure occurs (GrB_assign
 //      in particular).  See src/test/test_vector for an example.
 
-LAGRAPH_PUBLIC int LG_brutal_setup (char *msg) ;
-LAGRAPH_PUBLIC int LG_brutal_teardown (char *msg) ;
+LG_TEST_PUBLIC int LG_brutal_setup (char *msg) ;
+LG_TEST_PUBLIC int LG_brutal_teardown (char *msg) ;
 
-LAGRAPH_PUBLIC int64_t LG_brutal ;
-LAGRAPH_PUBLIC int64_t LG_nmalloc ;
+LG_TEST_PUBLIC extern int64_t LG_brutal ;
+LG_TEST_PUBLIC extern int64_t LG_nmalloc ;
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_malloc      // return pointer to allocated block of memory
 (
     size_t size             // # of bytes to allocate
 ) ;
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_calloc      // return pointer to allocated block of memory
 (
     size_t nitems,          // # of items to allocate
     size_t itemsize         // # of bytes per item
 ) ;
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void LG_brutal_free
 (
     void *p                 // block to free
 ) ;
 
-LAGRAPH_PUBLIC
+LG_TEST_PUBLIC
 void *LG_brutal_realloc     // return pointer to reallocated memory
 (
     void *p,                // block to realloc
diff --git a/src/test/include/acutest.h b/src/test/include/acutest.h
index 1d13044f06..e853a95764 100644
--- a/src/test/include/acutest.h
+++ b/src/test/include/acutest.h
@@ -1541,7 +1541,7 @@ acutest_cmdline_callback_(int id, const char* arg)
             acutest_worker_index_ = atoi(arg);
             break;
         case 'x':
-            acutest_xml_output_ = fopen(arg, "w");
+            acutest_xml_output_ = fopen(arg, "wb");
             if (!acutest_xml_output_) {
                 fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno));
                 acutest_exit_(2);
diff --git a/src/test/test_ConnectedComponents.c b/src/test/test_ConnectedComponents.c
index 9ae9fe9587..9140b2a9b4 100644
--- a/src/test/test_ConnectedComponents.c
+++ b/src/test/test_ConnectedComponents.c
@@ -23,6 +23,9 @@
 #include "LAGraphX.h"
 #include "LG_alg_internal.h"
 
+#undef NDEBUG
+#include <assert.h>
+
 char msg [LAGRAPH_MSG_LEN] ;
 LAGraph_Graph G = NULL ;
 #define LEN 512
@@ -82,6 +85,7 @@ void test_cc_matrices (void)
 {
 
     OK (LAGraph_Init (msg)) ;
+    // OK (GxB_set (GxB_BURBLE, true)) ;
 
     for (int k = 0 ; ; k++)
     {
@@ -122,6 +126,7 @@ void test_cc_matrices (void)
 
             // check the result
             OK (LG_check_cc (C, G, msg)) ;
+            OK (GrB_free (&C)) ;
 
             // find the connected components with LG_CC_FastSV5
             #if LAGRAPH_SUITESPARSE
@@ -134,14 +139,16 @@ void test_cc_matrices (void)
             #endif
 
             // find the connected components with LG_CC_Boruvka
+            int result = GrB_SUCCESS ;
             printf ("\n------ CC_BORUVKA:\n") ;
-            OK (LG_CC_Boruvka (&C2, G, msg)) ;
+            result = LG_CC_Boruvka (&C2, G, msg) ;
+            OK (result) ;
             ncomponents = count_connected_components (C2) ;
             TEST_CHECK (ncomponents == ncomp) ;
             OK (LG_check_cc (C2, G, msg)) ;
             OK (GrB_free (&C2)) ;
 
-            int result = LG_CC_Boruvka (NULL, G, msg) ;
+            result = LG_CC_Boruvka (NULL, G, msg) ;
             TEST_CHECK (result == GrB_NULL_POINTER) ;
 
             if (trial == 0)
@@ -167,7 +174,6 @@ void test_cc_matrices (void)
         }
 
         OK (LAGraph_Delete (&G, msg)) ;
-        OK (GrB_free (&C)) ;
     }
 
     OK (LAGraph_Finalize (msg)) ;
@@ -183,8 +189,11 @@ void test_cc_errors (void)
     printf ("\n") ;
 
     // check for null pointers
-    int result = LG_CC_Boruvka (NULL, NULL, msg) ;
+    int result = GrB_SUCCESS ;
+
+    result = LG_CC_Boruvka (NULL, NULL, msg) ;
     TEST_CHECK (result == GrB_NULL_POINTER) ;
+
     #if LAGRAPH_SUITESPARSE
     result = LG_CC_FastSV6 (NULL, NULL, msg) ;
     TEST_CHECK (result == GrB_NULL_POINTER) ;
@@ -203,6 +212,7 @@ void test_cc_errors (void)
     result = LG_CC_Boruvka (&C, G, msg) ;
     TEST_CHECK (result == -1001) ;
     printf ("result expected: %d msg:\n%s\n", result, msg) ;
+
     #if LAGRAPH_SUITESPARSE
     result = LG_CC_FastSV6 (&C, G, msg) ;
     TEST_CHECK (result == -1001) ;
diff --git a/src/test/test_MMRead.c b/src/test/test_MMRead.c
index 51a8e449a7..48ecdafd7c 100644
--- a/src/test/test_MMRead.c
+++ b/src/test/test_MMRead.c
@@ -467,7 +467,7 @@ void test_MMWrite (void)
         // create a file for comments
         //----------------------------------------------------------------------
 
-        FILE *fcomments = fopen (LG_DATA_DIR "comments.txt", "w") ;
+        FILE *fcomments = fopen (LG_DATA_DIR "comments.txt", "wb") ;
         TEST_CHECK (fcomments != NULL) ;
         fprintf (fcomments, " comments for %s\n", aname) ;
         fprintf (fcomments, " this file was created by test_MMRead.c\n") ;
@@ -480,7 +480,7 @@ void test_MMWrite (void)
 
         snprintf (filename, LEN, LG_DATA_DIR "comments_%s", aname) ;
         fcomments = fopen (LG_DATA_DIR "comments.txt", "r") ;
-        FILE *foutput = fopen (filename, "w") ;
+        FILE *foutput = fopen (filename, "wb") ;
         TEST_CHECK (foutput != NULL) ;
         TEST_CHECK (fcomments != NULL) ;
         OK (LAGraph_MMWrite (A, foutput, fcomments, msg)) ;
@@ -520,7 +520,7 @@ void test_MMWrite (void)
             double a ;
             OK (GrB_Matrix_extractElement (&a, A, 0, 0)) ;
             TEST_CHECK (isnan (a)) ;
-            foutput = fopen (filename, "w") ;
+            foutput = fopen (filename, "wb") ;
             fcomments = fopen (LG_DATA_DIR "comments.txt", "r") ;
             TEST_CHECK (foutput != NULL) ;
             OK (LAGraph_MMWrite (A, foutput, fcomments, msg)) ;
@@ -724,7 +724,7 @@ void test_array_pattern ( )
     // write it to a temporary file
     //--------------------------------------------------------------------------
 
-    FILE *f = tmpfile ( ) ; // fopen ("/tmp/mine.mtx", "w") ;
+    FILE *f = tmpfile ( ) ; // fopen ("/tmp/mine.mtx", "wb") ;
     OK (LAGraph_MMWrite (A, f, NULL, msg)) ;
     TEST_MSG ("Failed to write matrix to a temp file\n") ;
 //  OK (fclose (f)) ;
diff --git a/src/test/test_Malloc.c b/src/test/test_Malloc.c
index a28f73a3a4..9b1c531944 100644
--- a/src/test/test_Malloc.c
+++ b/src/test/test_Malloc.c
@@ -36,11 +36,15 @@ void test_malloc (void)
     OK (LAGraph_Free ((void **) &p, msg)) ;
     TEST_CHECK (p == NULL) ;
 
-    LAGraph_Malloc ((void **) &p, GrB_INDEX_MAX + 1, sizeof (char), msg) ;
-    TEST_CHECK (p == NULL) ;
+    size_t huge = 1 + SIZE_MAX/2 ;
 
-    LAGraph_Calloc ((void **) &p, GrB_INDEX_MAX + 1, sizeof (char), msg) ;
-    TEST_CHECK (p == NULL) ;
+    if (sizeof (size_t) >= sizeof (uint64_t))
+    {
+        LAGraph_Malloc ((void **) &p, huge, sizeof (char), msg) ;
+        TEST_CHECK (p == NULL) ;    // was FAIL
+        LAGraph_Calloc ((void **) &p, huge, sizeof (char), msg) ;
+        TEST_CHECK (p == NULL) ;    // was FAIL
+    }
 
     OK (LAGraph_Calloc ((void **) &p, 42, sizeof (char), msg)) ;
     for (int k = 0 ; k < 42 ; k++)
@@ -74,18 +78,22 @@ void test_malloc (void)
     TEST_CHECK (p == NULL) ;
 
     OK (LAGraph_Realloc ((void **) &p, 80, 0, sizeof (char), msg)) ;
+
+    if (sizeof (size_t) >= sizeof (uint64_t))
+    {
+        int s = (LAGraph_Realloc ((void **) &p, huge, 80, sizeof (char), msg)) ;
+        TEST_CHECK (s == GrB_OUT_OF_MEMORY) ;  // was FAIL
+    }
+
     for (int k = 0 ; k < 80 ; k++)
     {
         p [k] = (char) k ;
     }
 
-    int status = (LAGraph_Realloc ((void **) &p, GrB_INDEX_MAX+1, 80, sizeof (char), msg)) ;
-    TEST_CHECK (status == GrB_OUT_OF_MEMORY) ;
-
     OK (LAGraph_Realloc ((void **) &p, 80, 80, sizeof (char), msg)) ;
     for (int k = 0 ; k < 80 ; k++)
     {
-        TEST_CHECK (p [k] == (char) k) ;
+        TEST_CHECK (p [k] == (char) k) ;    // was FAIL
     }
 
     LAGraph_Realloc_function = NULL ;
@@ -93,7 +101,7 @@ void test_malloc (void)
     OK (LAGraph_Realloc ((void **) &p, 100, 80, sizeof (char), msg)) ;
     for (int k = 0 ; k < 80 ; k++)
     {
-        TEST_CHECK (p [k] == (char) k) ;
+        TEST_CHECK (p [k] == (char) k) ;    // was FAIL
     }
 
     OK (LAGraph_Free ((void **) &p, NULL)) ;
diff --git a/src/test/test_Xinit.c b/src/test/test_Xinit.c
index 064e8ab991..a968cdd8cb 100644
--- a/src/test/test_Xinit.c
+++ b/src/test/test_Xinit.c
@@ -2,7 +2,7 @@
 // LAGraph/src/test/test_Xinit.c:  test LAGr_Init and LAGraph_Global
 //------------------------------------------------------------------------------
 
-// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 //
 // For additional details (including references to third party source code and
@@ -16,6 +16,11 @@
 //------------------------------------------------------------------------------
 
 #include "LAGraph_test.h"
+#include "LAGraphX.h"
+
+// functions defined in LAGr_Init.c:
+LAGRAPH_PUBLIC void LG_set_LAGr_Init_has_been_called (bool setting) ;
+LAGRAPH_PUBLIC bool LG_get_LAGr_Init_has_been_called (void) ;
 
 //------------------------------------------------------------------------------
 // global variables
@@ -30,30 +35,43 @@ char msg [LAGRAPH_MSG_LEN] ;
 void test_Xinit (void)
 {
 
-    printf ("\nTesting LAGr_Init:\n") ;
+    printf ("\nTesting LAGr_Init: with expected errors\n") ;
 
     TEST_CHECK (LAGr_Init (GrB_NONBLOCKING, NULL, NULL, NULL, NULL, msg)
         == GrB_NULL_POINTER) ;
-    printf ("msg: %s\n", msg) ;
+    printf ("msg: [%s]\n", msg) ;
 
     TEST_CHECK (LAGr_Init (GrB_NONBLOCKING, malloc, NULL, NULL, NULL, msg)
         == GrB_NULL_POINTER) ;
-    printf ("msg: %s\n", msg) ;
+    printf ("msg: [%s]\n", msg) ;
 
     TEST_CHECK (LAGr_Init (GrB_NONBLOCKING, NULL, NULL, NULL, free, msg)
         == GrB_NULL_POINTER) ;
-    printf ("msg: %s\n", msg) ;
+    printf ("msg: [%s]\n", msg) ;
 
     OK (LAGr_Init (GrB_NONBLOCKING, malloc, calloc, realloc, free, msg)) ;
     printf ("msg: [%s]\n", msg) ;
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == true) ;
 
     // LAGr_Init cannot be called twice
     int status = LAGr_Init (GrB_NONBLOCKING,
         malloc, calloc, realloc, free, msg) ;
     TEST_CHECK (status != GrB_SUCCESS) ;
-    printf ("msg: %s\n", msg) ;
+    printf ("msg: [%s]\n", msg) ;
 
     OK (LAGraph_Finalize (msg)) ;
+
+    // the flag is still set after LAGraph_Finalize has been called,
+    // per LAGraph policy
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == true) ;
+
+    // reset and try again
+    LG_set_LAGr_Init_has_been_called (false) ;
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == false) ;
+    OK (LAGr_Init (GrB_NONBLOCKING, malloc, calloc, realloc, free, msg)) ;
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == true) ;
+    OK (LAGraph_Finalize (msg)) ;
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == true) ;
 }
 
 //------------------------------------------------------------------------------
@@ -61,7 +79,6 @@ void test_Xinit (void)
 //------------------------------------------------------------------------------
 
 #if LAGRAPH_SUITESPARSE
-LAGRAPH_PUBLIC bool LG_init_has_been_called ;
 void test_Xinit_brutal (void)
 {
     // no brutal memory failures, but test LG_brutal_malloc/calloc/realloc/free
@@ -127,22 +144,29 @@ void test_Xinit_brutal (void)
         }
     }
 
+    TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == true) ;
+
     for (int nbrutal = 0 ; nbrutal < 1000 ; nbrutal++)
     {
         LG_brutal = nbrutal ;
+        // reset both GraphBLAS and LAGraph
         GB_Global_GrB_init_called_set (false) ;
-        LG_init_has_been_called = false ;
+        LG_set_LAGr_Init_has_been_called (false) ;
+        TEST_CHECK (LG_get_LAGr_Init_has_been_called ( ) == false) ;
+        // try to initialize GraphBLAS and LAGraph
         int result = LAGr_Init (GrB_NONBLOCKING,
             LG_brutal_malloc, LG_brutal_calloc,
             LG_brutal_realloc, LG_brutal_free, msg) ;
         if (result == 0)
         {
+            // success
             OK (LAGraph_Finalize (msg)) ;
             printf ("LAGr_Init: finally: %d %g\n", nbrutal,
                 (double) LG_nmalloc) ;
             TEST_CHECK (LG_nmalloc == 0) ;
             break ;
         }
+        // failure: free anything partially allocated
         OK (LAGraph_Finalize (msg)) ;
     }
 }
diff --git a/src/test/test_minmax.c b/src/test/test_minmax.c
index 540d573b9e..799a9077c0 100644
--- a/src/test/test_minmax.c
+++ b/src/test/test_minmax.c
@@ -80,7 +80,7 @@ const matrix_info files [ ] =
     {                  1,                  1, "matrix_fp32_structure.mtx" } ,
     {          -INFINITY,           INFINITY, "matrix_fp64.mtx" } ,
     {             -32768,              32767, "matrix_int16.mtx" } ,
-    {        -2147483648,         2147483647, "matrix_int32.mtx" } ,
+    {      -2147483648.0,         2147483647, "matrix_int32.mtx" } ,
     {               -128,                127, "matrix_int8.mtx" } ,
     {                  0,              65535, "matrix_uint16.mtx" } ,
     {                  0,         4294967295, "matrix_uint32.mtx" } ,
@@ -185,7 +185,7 @@ void test_minmax (void)
         TEST_CASE (aname) ;
         printf ("\n============= %2d: %s\n", k, aname) ;
         snprintf (filename, LEN, LG_DATA_DIR "%s", aname) ;
-        FILE *f = fopen (filename, "r") ;
+        FILE *f = fopen (filename, "rb") ;
         TEST_CHECK (f != NULL) ;
         OK (LAGraph_MMRead (&A, f, msg)) ;
         OK (fclose (f)) ;
@@ -212,6 +212,10 @@ void test_minmax (void)
         double emin2 = 0 ;
         double emax2 = 0 ;
 
+        printf ("min/max as GrB_Scalars:\n") ;
+        GxB_print (G->emin, 3) ;
+        GxB_print (G->emax, 3) ;
+
         int result ;
         result = GrB_Scalar_extractElement_FP64 (&emin2, G->emin) ;
         printf ("min: %g %g err %g\n", emin1, emin2, emin1 - emin2) ;
@@ -223,6 +227,29 @@ void test_minmax (void)
         {
             TEST_CHECK (result == GrB_SUCCESS) ;
         }
+
+        #if 0
+        if (emin1 != emin2)
+        {
+            // failure on MSVC, OpenMP
+            // https://github.com/DrTimothyAldenDavis/SuiteSparse/actions/runs/6763376325/job/18380420493?pr=503
+            // now fixed.
+            printf ("Test failure, k: %d name: %s\n", k, aname) ;
+            printf ("emin1: %30.20g\n", emin1) ;
+            printf ("emin2: %30.20g\n", emin2) ;
+            OK (LAGraph_Matrix_Print (G->A, 5, stdout, msg)) ;
+
+            // extract as int64:
+            int64_t emin2_int64 = 0 ;
+            int64_t emax2_int64 = 0 ;
+            GrB_Scalar_extractElement_INT64 (&emin2_int64, G->emin) ;
+            GrB_Scalar_extractElement_INT64 (&emax2_int64, G->emax) ;
+            printf ("emin2 int64: %" PRId64 "\n", emin2_int64) ;
+            printf ("emax2 int64: %" PRId64 "\n", emax2_int64) ;
+
+        }
+        #endif
+
         TEST_CHECK (emin1 == emin2) ;
 
         result = GrB_Scalar_extractElement_FP64 (&emax2, G->emax) ;
@@ -273,7 +300,7 @@ void test_minmax_int64 (void)
         TEST_CASE (aname) ;
         printf ("\n============= %2d: %s\n", k, aname) ;
         snprintf (filename, LEN, LG_DATA_DIR "%s", aname) ;
-        FILE *f = fopen (filename, "r") ;
+        FILE *f = fopen (filename, "rb") ;
         TEST_CHECK (f != NULL) ;
         OK (LAGraph_MMRead (&A, f, msg)) ;
         OK (fclose (f)) ;
@@ -350,7 +377,7 @@ void test_minmax_uint64 (void)
         TEST_CASE (aname) ;
         printf ("\n============= %2d: %s\n", k, aname) ;
         snprintf (filename, LEN, LG_DATA_DIR "%s", aname) ;
-        FILE *f = fopen (filename, "r") ;
+        FILE *f = fopen (filename, "rb") ;
         TEST_CHECK (f != NULL) ;
         OK (LAGraph_MMRead (&A, f, msg)) ;
         OK (fclose (f)) ;
diff --git a/src/utility/LAGr_Init.c b/src/utility/LAGr_Init.c
index 29146ac94b..31f3e449a6 100644
--- a/src/utility/LAGr_Init.c
+++ b/src/utility/LAGr_Init.c
@@ -2,7 +2,7 @@
 // LAGr_Init: start GraphBLAS and LAGraph, and set malloc/etc functions
 //------------------------------------------------------------------------------
 
-// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
+// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
 // SPDX-License-Identifier: BSD-2-Clause
 //
 // For additional details (including references to third party source code and
@@ -20,66 +20,95 @@
 #include "LG_internal.h"
 
 //------------------------------------------------------------------------------
-// LAGraph global objects
+// LG_LAGr_Init_has_been_called: a static value only accessible within this file
 //------------------------------------------------------------------------------
 
-bool LG_init_has_been_called = false ;
+// LG_LAGr_Init_has_been_called indicates if LAGr_Init has been called.
+// LAGr_Init (or LAGraph_Init) can be called only once, even after
+// LAGraph_Finalize has been called.  For testing purposes, the flag can be
+// cleared by src/test/test_Xinit, to allow LAGr_Init or LAGraph_Init to be
+// called again.
+
+static bool LG_LAGr_Init_has_been_called = false ;
+
+// LG_LAGr_Init_has_been_called is only modified or accessed by the following
+// two routines (even in this file).  The two functions are made accessible via
+// LAGRAPH_PUBLIC, only for testing purposes by src/test/test_Xinit.c.
+
+LAGRAPH_PUBLIC void LG_set_LAGr_Init_has_been_called (bool setting) ;
+LAGRAPH_PUBLIC bool LG_get_LAGr_Init_has_been_called (void) ;
+
+LAGRAPH_PUBLIC
+void LG_set_LAGr_Init_has_been_called (bool setting)
+{
+    LG_LAGr_Init_has_been_called = setting ;
+}
+
+LAGRAPH_PUBLIC
+bool LG_get_LAGr_Init_has_been_called (void)
+{
+    return (LG_LAGr_Init_has_been_called) ;
+}
+
+//------------------------------------------------------------------------------
+// LAGraph global objects
+//------------------------------------------------------------------------------
 
 // LAGraph_plus_first_T: using the GrB_PLUS_MONOID_T monoid and the
 // corresponding GrB_FIRST_T multiplicative operator.
-GrB_Semiring LAGraph_plus_first_int8   = NULL ;
-GrB_Semiring LAGraph_plus_first_int16  = NULL ;
-GrB_Semiring LAGraph_plus_first_int32  = NULL ;
-GrB_Semiring LAGraph_plus_first_int64  = NULL ;
-GrB_Semiring LAGraph_plus_first_uint8  = NULL ;
-GrB_Semiring LAGraph_plus_first_uint16 = NULL ;
-GrB_Semiring LAGraph_plus_first_uint32 = NULL ;
-GrB_Semiring LAGraph_plus_first_uint64 = NULL ;
-GrB_Semiring LAGraph_plus_first_fp32   = NULL ;
-GrB_Semiring LAGraph_plus_first_fp64   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_int8   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_int16  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_int32  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_int64  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_uint8  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_uint16 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_uint32 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_uint64 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_fp32   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_first_fp64   = NULL ;
 
 // LAGraph_plus_second_T: using the GrB_PLUS_MONOID_T monoid and the
 // corresponding GrB_SECOND_T multiplicative operator.
-GrB_Semiring LAGraph_plus_second_int8   = NULL ;
-GrB_Semiring LAGraph_plus_second_int16  = NULL ;
-GrB_Semiring LAGraph_plus_second_int32  = NULL ;
-GrB_Semiring LAGraph_plus_second_int64  = NULL ;
-GrB_Semiring LAGraph_plus_second_uint8  = NULL ;
-GrB_Semiring LAGraph_plus_second_uint16 = NULL ;
-GrB_Semiring LAGraph_plus_second_uint32 = NULL ;
-GrB_Semiring LAGraph_plus_second_uint64 = NULL ;
-GrB_Semiring LAGraph_plus_second_fp32   = NULL ;
-GrB_Semiring LAGraph_plus_second_fp64   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_int8   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_int16  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_int32  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_int64  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_uint8  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_uint16 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_uint32 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_uint64 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_fp32   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_second_fp64   = NULL ;
 
 // LAGraph_plus_one_T: using the GrB_PLUS_MONOID_T monoid and the
 // corresponding GrB_ONEB_T multiplicative operator.
-GrB_Semiring LAGraph_plus_one_int8   = NULL ;
-GrB_Semiring LAGraph_plus_one_int16  = NULL ;
-GrB_Semiring LAGraph_plus_one_int32  = NULL ;
-GrB_Semiring LAGraph_plus_one_int64  = NULL ;
-GrB_Semiring LAGraph_plus_one_uint8  = NULL ;
-GrB_Semiring LAGraph_plus_one_uint16 = NULL ;
-GrB_Semiring LAGraph_plus_one_uint32 = NULL ;
-GrB_Semiring LAGraph_plus_one_uint64 = NULL ;
-GrB_Semiring LAGraph_plus_one_fp32   = NULL ;
-GrB_Semiring LAGraph_plus_one_fp64   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_int8   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_int16  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_int32  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_int64  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_uint8  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_uint16 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_uint32 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_uint64 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_fp32   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_plus_one_fp64   = NULL ;
 
 
 // use LAGraph_any_one_bool, etc
 
 // LAGraph_any_one_T: using the GrB_MIN_MONOID_T for non-boolean types
 // or GrB_LOR_MONOID_BOOL for boolean, and the GrB_ONEB_T multiplicative op.
-GrB_Semiring LAGraph_any_one_bool   = NULL ;
-GrB_Semiring LAGraph_any_one_int8   = NULL ;
-GrB_Semiring LAGraph_any_one_int16  = NULL ;
-GrB_Semiring LAGraph_any_one_int32  = NULL ;
-GrB_Semiring LAGraph_any_one_int64  = NULL ;
-GrB_Semiring LAGraph_any_one_uint8  = NULL ;
-GrB_Semiring LAGraph_any_one_uint16 = NULL ;
-GrB_Semiring LAGraph_any_one_uint32 = NULL ;
-GrB_Semiring LAGraph_any_one_uint64 = NULL ;
-GrB_Semiring LAGraph_any_one_fp32   = NULL ;
-GrB_Semiring LAGraph_any_one_fp64   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_bool   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_int8   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_int16  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_int32  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_int64  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_uint8  = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_uint16 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_uint32 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_uint64 = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_fp32   = NULL ;
+LAGRAPH_PUBLIC GrB_Semiring LAGraph_any_one_fp64   = NULL ;
 
 //------------------------------------------------------------------------------
 // LAGr_Init
@@ -109,9 +138,8 @@ int LAGr_Init
     GrB_Info info ;
 
     // ensure LAGr_Init has not already been called
-    LG_ASSERT_MSG (!LG_init_has_been_called, GrB_INVALID_VALUE,
+    LG_ASSERT_MSG (!LG_get_LAGr_Init_has_been_called ( ), GrB_INVALID_VALUE,
         "LAGr*_Init can only be called once") ;
-    LG_init_has_been_called = true ;
 
     //--------------------------------------------------------------------------
     // start GraphBLAS
@@ -297,5 +325,7 @@ int LAGr_Init
     GRB_TRY (GrB_Semiring_new (&LAGraph_any_one_fp64,
         GrB_MIN_MONOID_FP64   , GrB_ONEB_FP64  )) ;
 
+    LG_set_LAGr_Init_has_been_called (true) ;
     return (GrB_SUCCESS) ;
 }
+
diff --git a/src/utility/LAGr_SortByDegree.c b/src/utility/LAGr_SortByDegree.c
index c2ed0aefc9..3e1f16a642 100644
--- a/src/utility/LAGr_SortByDegree.c
+++ b/src/utility/LAGr_SortByDegree.c
@@ -118,8 +118,9 @@ int LAGr_SortByDegree
     // construct the pair [D,P] to sort
     //--------------------------------------------------------------------------
 
+    int64_t k;
     #pragma omp parallel for num_threads(nthreads) schedule(static)
-    for (int64_t k = 0 ; k < n ; k++)
+    for (k = 0 ; k < n ; k++)
     {
         D [k] = 0 ;
         P [k] = k ;
@@ -133,7 +134,7 @@ int LAGr_SortByDegree
     {
         // sort [D,P] in ascending order of degree, tie-breaking on P
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int64_t k = 0 ; k < nvals ; k++)
+        for (k = 0 ; k < nvals ; k++)
         {
             D [W0 [k]] = W1 [k] ;
         }
@@ -142,7 +143,7 @@ int LAGr_SortByDegree
     {
         // sort [D,P] in descending order of degree, tie-breaking on P
         #pragma omp parallel for num_threads(nthreads) schedule(static)
-        for (int64_t k = 0 ; k < nvals ; k++)
+        for (k = 0 ; k < nvals ; k++)
         {
             D [W0 [k]] = -W1 [k] ;
         }
diff --git a/src/utility/LAGraph_Calloc.c b/src/utility/LAGraph_Calloc.c
index 17690d970d..23f5ffc630 100644
--- a/src/utility/LAGraph_Calloc.c
+++ b/src/utility/LAGraph_Calloc.c
@@ -40,8 +40,7 @@ int LAGraph_Calloc
 
     // compute the size and check for integer overflow
     size_t size ;
-    bool ok = LG_Multiply_size_t (&size, nitems, size_of_item) ;
-    if (!ok || nitems > GrB_INDEX_MAX || size_of_item > GrB_INDEX_MAX)
+    if (!LG_Multiply_size_t (&size, nitems, size_of_item))
     {
         // overflow
         return (GrB_OUT_OF_MEMORY) ;
diff --git a/src/utility/LAGraph_Global.c b/src/utility/LAGraph_Global.c
index a74320f2d2..c102d297d8 100644
--- a/src/utility/LAGraph_Global.c
+++ b/src/utility/LAGraph_Global.c
@@ -22,10 +22,10 @@
 //------------------------------------------------------------------------------
 
 // These are modified by LAGraph_Init and LAGr_Init:
-void * (* LAGraph_Malloc_function  ) (size_t)         = malloc ;
-void * (* LAGraph_Calloc_function  ) (size_t, size_t) = calloc ;
-void * (* LAGraph_Realloc_function ) (void *, size_t) = realloc ;
-void   (* LAGraph_Free_function    ) (void *)         = free ;
+LAGRAPH_PUBLIC void * (* LAGraph_Malloc_function  ) (size_t)         = malloc ;
+LAGRAPH_PUBLIC void * (* LAGraph_Calloc_function  ) (size_t, size_t) = calloc ;
+LAGRAPH_PUBLIC void * (* LAGraph_Realloc_function ) (void *, size_t) = realloc ;
+LAGRAPH_PUBLIC void   (* LAGraph_Free_function    ) (void *)         = free ;
 
 //------------------------------------------------------------------------------
 // threading control
diff --git a/src/utility/LAGraph_Malloc.c b/src/utility/LAGraph_Malloc.c
index 98461ad1a0..a178c3c316 100644
--- a/src/utility/LAGraph_Malloc.c
+++ b/src/utility/LAGraph_Malloc.c
@@ -40,8 +40,7 @@ int LAGraph_Malloc
 
     // compute the size and check for integer overflow
     size_t size ;
-    bool ok = LG_Multiply_size_t (&size, nitems, size_of_item) ;
-    if (!ok || nitems > GrB_INDEX_MAX || size_of_item > GrB_INDEX_MAX)
+    if (!LG_Multiply_size_t (&size, nitems, size_of_item))
     {
         // overflow
         return (GrB_OUT_OF_MEMORY) ;
diff --git a/src/utility/LAGraph_Realloc.c b/src/utility/LAGraph_Realloc.c
index 4e1c4387b2..7e118d763c 100644
--- a/src/utility/LAGraph_Realloc.c
+++ b/src/utility/LAGraph_Realloc.c
@@ -82,8 +82,7 @@ int LAGraph_Realloc
     size_t newsize, oldsize ;
     bool ok = LG_Multiply_size_t (&newsize, nitems_new, size_of_item)
            && LG_Multiply_size_t (&oldsize, nitems_old, size_of_item) ;
-
-    if (!ok || nitems_new > GrB_INDEX_MAX || size_of_item > GrB_INDEX_MAX)
+    if (!ok)
     {
         // overflow
         return (GrB_OUT_OF_MEMORY) ;
diff --git a/src/utility/LG_internal.h b/src/utility/LG_internal.h
index 30bc9e24ab..5935dfd25a 100644
--- a/src/utility/LG_internal.h
+++ b/src/utility/LG_internal.h
@@ -25,9 +25,9 @@
 // include files
 //------------------------------------------------------------------------------
 
-#define LG_LIBRARY
 #include <ctype.h>
 #include "LAGraph.h"
+#undef I
 
 #if defined ( __linux__ )
 #include <malloc.h>
@@ -353,11 +353,11 @@ MM_storage_enum ;
 // LG_PART and LG_PARTITION: definitions for partitioning an index range
 //------------------------------------------------------------------------------
 
-LAGRAPH_PUBLIC
+LAGRAPH_PUBLIC extern
 int LG_nthreads_outer ; // # of threads to use at the higher level of a nested
                         // parallel region in LAGraph.  Default: 1.
 
-LAGRAPH_PUBLIC
+LAGRAPH_PUBLIC extern
 int LG_nthreads_inner ; // # of threads to use at the lower level of a nested
                         // parallel region, or to use inside GraphBLAS.
                         // Default: the value obtained by omp_get_max_threads
diff --git a/src/utility/LG_msort1.c b/src/utility/LG_msort1.c
index 4d8f8ec68d..b69a8ad9a2 100644
--- a/src/utility/LG_msort1.c
+++ b/src/utility/LG_msort1.c
@@ -409,7 +409,7 @@ int LG_msort1
         // already sorted with respect to each other.
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two A sublists into one W sublist
             LG_msort_1b_create_merge_tasks (
@@ -438,7 +438,7 @@ int LG_msort1
         //----------------------------------------------------------------------
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two W sublists into one A sublist
             LG_msort_1b_create_merge_tasks (
diff --git a/src/utility/LG_msort2.c b/src/utility/LG_msort2.c
index 14159c4e7d..f7baa47312 100644
--- a/src/utility/LG_msort2.c
+++ b/src/utility/LG_msort2.c
@@ -427,7 +427,7 @@ int LG_msort2
         // already sorted with respect to each other.
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two A sublists into one W sublist
             LG_msort_2b_create_merge_tasks (
@@ -456,7 +456,7 @@ int LG_msort2
         //----------------------------------------------------------------------
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two W sublists into one A sublist
             LG_msort_2b_create_merge_tasks (
diff --git a/src/utility/LG_msort3.c b/src/utility/LG_msort3.c
index f46ed6203e..031d4a302f 100644
--- a/src/utility/LG_msort3.c
+++ b/src/utility/LG_msort3.c
@@ -440,7 +440,7 @@ int LG_msort3
         //----------------------------------------------------------------------
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two A sublists into one W sublist
             LG_msort_3b_create_merge_tasks (
@@ -469,7 +469,7 @@ int LG_msort3
         //----------------------------------------------------------------------
 
         // this could be done in parallel if ntasks was large
-        for (int tid = 0 ; tid < ntasks ; tid += 2*nt)
+        for (tid = 0 ; tid < ntasks ; tid += 2*nt)
         {
             // create 2*nt tasks to merge two W sublists into one A sublist
             LG_msort_3b_create_merge_tasks (