diff --git a/biology/salmon/Makefile b/biology/salmon/Makefile index 74631d470a17..8332ba416d74 100644 --- a/biology/salmon/Makefile +++ b/biology/salmon/Makefile @@ -1,51 +1,59 @@ PORTNAME= salmon DISTVERSIONPREFIX= v -DISTVERSION= 1.10.2 -PORTREVISION= 8 +DISTVERSION= 1.10.3 CATEGORIES= biology MAINTAINER= jwb@FreeBSD.org COMMENT= Transcript-level quantification of RNA-seq from lightweight alignments WWW= https://github.com/COMBINE-lab/salmon LICENSE= GPLv3 LICENSE_FILE= ${WRKSRC}/LICENSE NOT_FOR_ARCHS= armv6 armv7 i386 mips powerpc powerpcspe NOT_FOR_ARCHS_REASON= Requires 64-bit processor # libtool and auto* are run manually in submodules, so don't put them in USES BUILD_DEPENDS= bash:shells/bash \ cereal>=1.3.0:devel/cereal \ libgff==2.0.0:biology/libgff \ libtool:devel/libtool \ autoreconf:devel/autoconf \ - aclocal:devel/automake -LIB_DEPENDS= libboost_system.so:devel/boost-libs \ - libtbb.so:devel/onetbb \ - libcurl.so:ftp/curl + aclocal:devel/automake \ + eigen>0:math/eigen3 \ + libdivide>0:math/libdivide \ + curl>0:ftp/curl +LIB_DEPENDS= libtbb.so:devel/onetbb USES= cmake:noninja gmake localbase shebangfix USE_GITHUB= yes +# Can't unbundle io_lib unless we also unbundle htscodecs from io_lib, +# which is a nightmare: explicitly integrated into configure files and +# installs htscodecs files, conflicting with separate htscodecs port. GH_ACCOUNT= COMBINE-lab -GH_TUPLE+= COMBINE-lab:pufferfish:salmon-v1.10.2:pf/external/pufferfish -GH_TUPLE+= jkbonfield:io_lib:io_lib-1-14-15:sio/external/staden-io_lib -GH_TUPLE+= samtools:htscodecs:5aecc6e:htscodec/external/staden-io_lib/htscodecs +GH_TUPLE+= COMBINE-lab:pufferfish:salmon-v${DISTVERSION}:pf/external/pufferfish +GH_TUPLE+= jkbonfield:io_lib:io_lib-1-15-1:sio/external/staden-io_lib +# Update commit hash from io_lib release branch +GH_TUPLE+= samtools:htscodecs:de42211:htscodec/external/staden-io_lib/htscodecs SHEBANG_FILES= scripts/* PLIST_FILES= bin/salmon CMAKE_ARGS+= -DHAVE_FAST_MALLOC:BOOL=on \ -DBOOST_ROOT:PATH=${LOCALBASE} \ -DFETCHED_PUFFERFISH:BOOL=on \ -DFETCHED_LIBGFF:BOOL=on \ -DFETCH_STADEN:BOOL=true +WITH_DEBUG= yes +CXXFLAGS+= -I${LOCALBASE}/include/eigen3 LDFLAGS+= -lpthread pre-configure: + ${RM} -rf ${WRKSRC}/include/eigen3 \ + ${WRKSRC}/external/pufferfish/include/libdivide (cd ${WRKSRC}/external/staden-io_lib && ./bootstrap) do-install: ${INSTALL_PROGRAM} ${BUILD_WRKSRC}/src/salmon ${STAGEDIR}${PREFIX}/bin .include diff --git a/biology/salmon/distinfo b/biology/salmon/distinfo index 42eb0d9ee404..ea5ed9dddde3 100644 --- a/biology/salmon/distinfo +++ b/biology/salmon/distinfo @@ -1,9 +1,9 @@ -TIMESTAMP = 1689958260 -SHA256 (COMBINE-lab-salmon-v1.10.2_GH0.tar.gz) = 976989182160fef3afb4429ee8b85d8dd39ed6ca212bb14d6a65cde0e985fb98 -SIZE (COMBINE-lab-salmon-v1.10.2_GH0.tar.gz) = 7193261 -SHA256 (COMBINE-lab-pufferfish-salmon-v1.10.2_GH0.tar.gz) = b90ce8079c375136d12e37bc23e451ae34a49d49c54f6cdd2050ba8add758ab4 -SIZE (COMBINE-lab-pufferfish-salmon-v1.10.2_GH0.tar.gz) = 3368053 -SHA256 (jkbonfield-io_lib-io_lib-1-14-15_GH0.tar.gz) = 4444c78846e49a493ff09d56d55ebe61140bb0a76ec5fa1c27eff13ec9dabd8b -SIZE (jkbonfield-io_lib-io_lib-1-14-15_GH0.tar.gz) = 3382074 -SHA256 (samtools-htscodecs-5aecc6e_GH0.tar.gz) = 3abb6a8516761bf0db5149c3d6c077e2d540470180245c2afb1f4400158b1f54 -SIZE (samtools-htscodecs-5aecc6e_GH0.tar.gz) = 3191442 +TIMESTAMP = 1753565795 +SHA256 (COMBINE-lab-salmon-v1.10.3_GH0.tar.gz) = a053fba63598efc4ade3684aa2c8e8e2294186927d4fcdf1041c36edc2aa0871 +SIZE (COMBINE-lab-salmon-v1.10.3_GH0.tar.gz) = 7193092 +SHA256 (COMBINE-lab-pufferfish-salmon-v1.10.3_GH0.tar.gz) = 5d345ba30f22ff4448f4bf2920d2246a11cc38b203e12828c07b2612e41d2951 +SIZE (COMBINE-lab-pufferfish-salmon-v1.10.3_GH0.tar.gz) = 3368105 +SHA256 (jkbonfield-io_lib-io_lib-1-15-1_GH0.tar.gz) = 5fef32bb10991b388b4a92292e58d6ef8e7eda812ab2d6a10daaca9a757e6302 +SIZE (jkbonfield-io_lib-io_lib-1-15-1_GH0.tar.gz) = 3381908 +SHA256 (samtools-htscodecs-de42211_GH0.tar.gz) = 65e632bf00e2e456a3040e8a4748dbd33161595029ba49dec89d5301ebdd4de6 +SIZE (samtools-htscodecs-de42211_GH0.tar.gz) = 3200933 diff --git a/biology/salmon/files/patch-CMakeLists.txt b/biology/salmon/files/patch-CMakeLists.txt index 5a6bd2de2f02..36038f452843 100644 --- a/biology/salmon/files/patch-CMakeLists.txt +++ b/biology/salmon/files/patch-CMakeLists.txt @@ -1,123 +1,155 @@ ---- CMakeLists.txt.orig 2023-07-21 14:03:31 UTC +--- CMakeLists.txt.orig 2025-07-26 11:52:41 UTC +++ CMakeLists.txt @@ -310,14 +310,16 @@ endif() # Grab pufferfish source --- DURING CONFIGURE TIME! # #### -if(NOT FETCHED_PUFFERFISH) -+ ++# if(NOT FETCHED_PUFFERFISH) +# Fetched by GH_TUPLE in FreeBSD port +# if(NOT FETCHED_PUFFERFISH) exec_program(${CMAKE_CURRENT_SOURCE_DIR}/scripts/fetchPufferfish.sh RETURN_VALUE FETCH_PF_SCRIPT_RET) message(STATUS "fetch PUFFERFISH exit code ${FETCH_PF_SCRIPT_RET}") if(NOT (FETCH_PF_SCRIPT_RET EQUAL 0)) message(FATAL_ERROR "Could not fetch pufferfish source [fetchPufferfish.sh returned exit code ${FETCH_PF_SCRIPT_RET}].") endif() set(FETCHED_PUFFERFISH TRUE CACHE BOOL "Has pufferfish been fetched?" FORCE) -endif() +# endif() ## # Super-secret override -@@ -364,7 +366,10 @@ if(NOT Iconv_IS_BUILT_IN) +@@ -364,7 +366,11 @@ endif() set(ICONV_LIB Iconv::Iconv) endif() -find_package(LibLZMA) ++# find_package(LibLZMA) +# lzma is in FreeBSD base +# find_package(LibLZMA) +set(LIBLZMA_FOUND TRUE) +set(LIBLZMA_LIBRARIES /usr/lib/liblzma.a /usr/lib/libmd.a) if(NOT LIBLZMA_FOUND) message("Will attempt to fetch and build liblzma") message("=======================================") -@@ -381,8 +386,8 @@ externalproject_add(liblzma +@@ -381,8 +387,11 @@ externalproject_add(liblzma INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/install BUILD_IN_SOURCE TRUE CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/external/xz-5.2.2/configure --prefix= CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} CFLAGS=${EXTRA_CMAKE_INCLUDE_FLAGS} CPPFLAGS=${EXTRA_CMAKE_INCLUDE_FLAGS} LDFLAGS=${EXTRA_CMAKE_LIBRARY_FLAGS} - BUILD_COMMAND make ${QUIET_MAKE} - INSTALL_COMMAND make ${QUIET_MAKE} install ++# BUILD_COMMAND make ${QUIET_MAKE} ++# INSTALL_COMMAND make ${QUIET_MAKE} install ++# FreeBSD make is bsdmake + BUILD_COMMAND gmake ${QUIET_MAKE} + INSTALL_COMMAND gmake ${QUIET_MAKE} install ) # Tell cmake that the external project generated a library so we can -@@ -411,8 +416,8 @@ externalproject_add(libbz2 +@@ -411,8 +420,11 @@ externalproject_add(libbz2 INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/install BUILD_IN_SOURCE TRUE CONFIGURE_COMMAND "" - BUILD_COMMAND make ${QUIET_MAKE} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} - INSTALL_COMMAND make ${QUIET_MAKE} install PREFIX= ++# BUILD_COMMAND make ${QUIET_MAKE} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ++# INSTALL_COMMAND make ${QUIET_MAKE} install PREFIX= ++# FreeBSD make is bsdmake + BUILD_COMMAND gmake ${QUIET_MAKE} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} + INSTALL_COMMAND gmake ${QUIET_MAKE} install PREFIX= ) # Tell cmake that the external project generated a library so we can # add dependencies here instead of later -@@ -609,9 +614,11 @@ if (NOT CEREAL_FOUND) +@@ -577,9 +589,11 @@ endif() endif() ## Try and find TBB first -find_package(TBB 2021.4 - HINTS ${TBB_ROOT_SEARCH} - COMPONENTS tbb tbbmalloc tbbmalloc_proxy) +# find_package(TBB 2021.4 +# HINTS ${TBB_ROOT_SEARCH} +# COMPONENTS tbb tbbmalloc tbbmalloc_proxy) +# tbbmalloc_proxy is rolled into tbbmalloc in FreeBSD ports +find_package(TBB 2021.4 COMPONENTS tbb tbbmalloc) if (${TBB_FOUND}) if (${TBB_VERSION} VERSION_GREATER_EQUAL 2021.4) -@@ -791,22 +798,16 @@ endif() +@@ -761,25 +775,28 @@ if (NOT LIBSTADENIO_FOUND) if (NOT LIBSTADENIO_FOUND) message("Build system will compile Staden IOLib") message("==================================================================") + # stadenio is downloaded by GH_TUPLE in FreeBSD port externalproject_add(libstadenio - DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external -- DOWNLOAD_COMMAND curl -k -L https://github.com/jkbonfield/io_lib/releases/download/io_lib-1-14-15/io_lib-1.14.15.tar.gz -o staden-io_lib-v1.14.15.tar.gz && -- ${SHASUM} 20814c4365e1e2fe6630fb11d0df370dec4c5688af3871de7f1cb0129671401e staden-io_lib-v1.14.15.tar.gz && -- mkdir -p staden-io_lib-1.14.15 && -- tar -xzf staden-io_lib-v1.14.15.tar.gz --strip-components=1 -C staden-io_lib-1.14.15 && +- DOWNLOAD_COMMAND curl -k -L https://github.com/jkbonfield/io_lib/releases/download/io_lib-1-15-0/io_lib-1.15.0.tar.gz -o staden-io_lib-v1.15.0.tar.gz && +- ${SHASUM} ad343dac7c77086db1b54585c5887b26eda6430d1639d111dd3304c3b749494f staden-io_lib-v1.15.0.tar.gz && +- mkdir -p staden-io_lib-1.15.0 && +- tar -xzf staden-io_lib-v1.15.0.tar.gz --strip-components=1 -C staden-io_lib-1.15.0 && - rm -fr staden-io_lib && -- mv -f staden-io_lib-1.14.15 staden-io_lib +- mv -f staden-io_lib-1.15.0 staden-io_lib && +- curl -k -L https://github.com/samtools/htscodecs/releases/download/v1.6.0/htscodecs-1.6.0.tar.gz -o htscodecs-1.6.0.tar.gz && +- mkdir -p htscodecs-1.6.0 && +- tar -xzf htscodecs-1.6.0.tar.gz --strip-components=1 -C htscodecs-1.6.0 && +- rm -fr staden-io_lib/htscodecs && +- mv -f htscodecs-1.6.0 staden-io_lib/htscodecs ++ # DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external ++ # DOWNLOAD_COMMAND curl -k -L https://github.com/jkbonfield/io_lib/releases/download/io_lib-1-15-0/io_lib-1.15.0.tar.gz -o staden-io_lib-v1.15.0.tar.gz && ++ # ${SHASUM} ad343dac7c77086db1b54585c5887b26eda6430d1639d111dd3304c3b749494f staden-io_lib-v1.15.0.tar.gz && ++ # mkdir -p staden-io_lib-1.15.0 && ++ # tar -xzf staden-io_lib-v1.15.0.tar.gz --strip-components=1 -C staden-io_lib-1.15.0 && ++ # rm -fr staden-io_lib && ++ # mv -f staden-io_lib-1.15.0 staden-io_lib && ++ # curl -k -L https://github.com/samtools/htscodecs/releases/download/v1.6.0/htscodecs-1.6.0.tar.gz -o htscodecs-1.6.0.tar.gz && ++ # mkdir -p htscodecs-1.6.0 && ++ # tar -xzf htscodecs-1.6.0.tar.gz --strip-components=1 -C htscodecs-1.6.0 && ++ # rm -fr staden-io_lib/htscodecs && ++ # mv -f htscodecs-1.6.0 staden-io_lib/htscodecs SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/staden-io_lib INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/install CONFIGURE_COMMAND ./configure --enable-shared=no --without-libcurl --prefix= LDFLAGS=${LIBSTADEN_LDFLAGS} CFLAGS=${LIBSTADEN_CFLAGS} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} - BUILD_COMMAND make ${QUIET_MAKE} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} CFLAGS+=${STADEN_INC} CFLAGS+=${STADEN_LIB} LDFLAGS+=${EXTRA_CMAKE_LIBRARY_FLAGS} CFLAGS+=${EXTRA_CMAKE_INCLUDE_FLAGS} CFLAGS+=${LZFLAG} CFLAGS+=${SCHAR_FLAG} ++ # FreeBSD make is bsdmake + BUILD_COMMAND gmake ${QUIET_MAKE} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} CFLAGS+=${STADEN_INC} CFLAGS+=${STADEN_LIB} LDFLAGS+=${EXTRA_CMAKE_LIBRARY_FLAGS} CFLAGS+=${EXTRA_CMAKE_INCLUDE_FLAGS} CFLAGS+=${LZFLAG} CFLAGS+=${SCHAR_FLAG} - - BUILD_IN_SOURCE 1 - INSTALL_COMMAND make install ++ # FreeBSD make is bsdmake + INSTALL_COMMAND gmake install ) if(NOT LIBLZMA_FOUND) ExternalProject_Add_StepDependencies(libstadenio build liblzma) -@@ -820,23 +821,9 @@ if (ASAN_BUILD) +@@ -793,23 +810,26 @@ else() set(FAST_MALLOC_LIB "") set(HAVE_FAST_MALLOC TRUE) else() - set(FAST_MALLOC_LIB "") - set(HAVE_FAST_MALLOC FALSE) -- -- # See if we have Jemalloc ++ # set(FAST_MALLOC_LIB "") ++ # set(HAVE_FAST_MALLOC FALSE) + + # See if we have Jemalloc - find_package(Jemalloc) - if(Jemalloc_FOUND) -- ## -- # Don't be so stringent about the version yet -- ## -- #if (NOT (${JEMALLOC_VERSION} VERSION_LESS 5.2.1)) ++ # find_package(Jemalloc) ++ # if(Jemalloc_FOUND) + ## + # Don't be so stringent about the version yet + ## + #if (NOT (${JEMALLOC_VERSION} VERSION_LESS 5.2.1)) - message("Found Jemalloc library --- using this memory allocator") - set(FAST_MALLOC_LIB ${JEMALLOC_LIBRARIES}) - set(HAVE_FAST_MALLOC TRUE) -- #else() -- # message("Fond Jemalloc version ${JEMALLOC_VERSION}, but require >= 5.2.1. Downloading newer version") -- #endif() ++ # message("Found Jemalloc library --- using this memory allocator") ++ # set(FAST_MALLOC_LIB ${JEMALLOC_LIBRARIES}) ++ # set(HAVE_FAST_MALLOC TRUE) + #else() + # message("Fond Jemalloc version ${JEMALLOC_VERSION}, but require >= 5.2.1. Downloading newer version") + #endif() - endif() ++ # endif() + # jemalloc is default on FreeBSD + set(FAST_MALLOC_LIB "/usr/lib/libc.so") + set(HAVE_FAST_MALLOC TRUE) endif() if(CONDA_BUILD) diff --git a/biology/salmon/files/patch-external_pufferfish_external_twopaco_graphconstructor_candidateoccurence.h b/biology/salmon/files/patch-external_pufferfish_external_twopaco_graphconstructor_candidateoccurence.h new file mode 100644 index 000000000000..8686f1695177 --- /dev/null +++ b/biology/salmon/files/patch-external_pufferfish_external_twopaco_graphconstructor_candidateoccurence.h @@ -0,0 +1,11 @@ +--- external/pufferfish/external/twopaco/graphconstructor/candidateoccurence.h.orig 2025-07-26 13:01:27 UTC ++++ external/pufferfish/external/twopaco/graphconstructor/candidateoccurence.h +@@ -58,7 +58,7 @@ namespace TwoPaCo + const CandidateOccurence & operator = (const CandidateOccurence & toCopy) + { + body_ = toCopy.body_; +- count_ = toCopy.count_; ++ count_.store(toCopy.count_.load(std::memory_order_relaxed)); + } + + void Inc() diff --git a/biology/salmon/files/patch-external_pufferfish_src_PuffAligner.cpp b/biology/salmon/files/patch-external_pufferfish_src_PuffAligner.cpp new file mode 100644 index 000000000000..682951604abe --- /dev/null +++ b/biology/salmon/files/patch-external_pufferfish_src_PuffAligner.cpp @@ -0,0 +1,14 @@ +--- external/pufferfish/src/PuffAligner.cpp.orig 2023-06-26 19:34:50 UTC ++++ external/pufferfish/src/PuffAligner.cpp +@@ -1,7 +1,10 @@ + #include "nonstd/string_view.hpp" + #include "PuffAligner.hpp" + #include "Util.hpp" +-#include "libdivide/libdivide.h" ++// Bundled libdivide causes build failures with clang19 ++// Use FreeBSD libdivde port instead ++// #include "libdivide/libdivide.h" ++#include + + std::string extractReadSeq(const std::string& readSeq, uint32_t rstart, uint32_t rend, bool isFw) { + std::string subseq = readSeq.substr(rstart, rend - rstart); diff --git a/biology/salmon/files/patch-scripts_fetchPufferfish.sh b/biology/salmon/files/patch-scripts_fetchPufferfish.sh index 566493a5e7ee..a1885fd1ff61 100644 --- a/biology/salmon/files/patch-scripts_fetchPufferfish.sh +++ b/biology/salmon/files/patch-scripts_fetchPufferfish.sh @@ -1,57 +1,64 @@ ---- scripts/fetchPufferfish.sh.orig 2023-07-21 13:59:29 UTC +--- scripts/fetchPufferfish.sh.orig 2025-07-26 17:38:39 UTC +++ scripts/fetchPufferfish.sh -@@ -11,52 +11,12 @@ CURR_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && p +@@ -11,53 +11,6 @@ INSTALL_DIR=${CURR_DIR}/../external/install EXTERNAL_DIR=${CURR_DIR}/../external INSTALL_DIR=${CURR_DIR}/../external/install -if [ -d ${EXTERNAL_DIR}/pufferfish ] ; then - rm -fr ${EXTERNAL_DIR}/pufferfish -fi -+# Pufferfish is downloaded using GH_TUPLE in the FreeBSD port, so remove -+# code here that downloads and unpacks - +- -if [ -d ${INSTALL_DIR}/include/pufferfish ] ; then - rm -fr ${INSTALL_DIR}/include/pufferfish -fi - -if [ -d ${INSTALL_DIR}/src/pufferfish ] ; then - rm -fr ${INSTALL_DIR}/src/pufferfish -fi - - SVER=salmon-v1.10.2 - #SVER=develop - #SVER=sketch-mode +-SVER=salmon-v1.10.3 +-#SVER=develop +-#SVER=sketch-mode - --EXPECTED_SHA256=f225b74833f71dcf767a565345224357fb091f90ce79717abc836814d9ccd101 +-EXPECTED_SHA256=52b6699de0d33814b73edb3455175568c2330d8014be017dce7b564e54134860 - -mkdir -p ${EXTERNAL_DIR} -curl -k -L https://github.com/COMBINE-lab/pufferfish/archive/${SVER}.zip -o ${EXTERNAL_DIR}/pufferfish.zip - -hashcheck="" -if exists sha256sum; then - hashcheck="sha256sum" -elif exists shasum; then - hashcheck="shasum -a256" -else - unset hashcheck -fi - - -if [ -z "${hashcheck-}" ]; then - echo "Couldn't find shasum command; can't verify contents of downloaded pufferfish"; -else - - if [[ $SVER != develop && $SVER != onetbb ]]; then - echo "${EXPECTED_SHA256} ${EXTERNAL_DIR}/pufferfish.zip" | ${hashcheck} -c - || { echo "pufferfish.zip did not match expected SHA1! Exiting."; exit 1; } - else - echo "not testing sha since pulling from develop" - fi -fi - - -rm -fr ${EXTERNAL_DIR}/pufferfish -unzip ${EXTERNAL_DIR}/pufferfish.zip -d ${EXTERNAL_DIR} -mv ${EXTERNAL_DIR}/pufferfish-${SVER} ${EXTERNAL_DIR}/pufferfish - +- mkdir -p ${INSTALL_DIR}/include/pufferfish + cp ${EXTERNAL_DIR}/pufferfish/include/ProgOpts.hpp ${INSTALL_DIR}/include/pufferfish +@@ -90,7 +43,6 @@ cp ${EXTERNAL_DIR}/pufferfish/include/BinWriter.hpp ${ + cp ${EXTERNAL_DIR}/pufferfish/include/BulkChunk.hpp ${INSTALL_DIR}/include/pufferfish + cp ${EXTERNAL_DIR}/pufferfish/include/BinWriter.hpp ${INSTALL_DIR}/include/pufferfish + +-cp -r ${EXTERNAL_DIR}/pufferfish/include/libdivide ${INSTALL_DIR}/include/pufferfish + cp -r ${EXTERNAL_DIR}/pufferfish/include/ksw2pp ${INSTALL_DIR}/include/pufferfish + # this is now automatically tracked and inherited via twopaco (on which libpuffer depends) + # cp -r ${EXTERNAL_DIR}/pufferfish/include/compact_vector ${INSTALL_DIR}/include/pufferfish