diff --git a/README.md b/README.md index 2d65d70d..e5ce0326 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ 3. [MinGW](#5-3) 4. [Cygwin](#5-4) 5. [Microsoft Visual C++](#5-5) + 6. [Unix](#5-6)
@@ -803,7 +804,6 @@ set "PS1=\! CYGWIN64:\u@\h:\w \$ " bash.exe -norc ``` - [TOC](#TOC)
@@ -827,8 +827,42 @@ set "PATH=C:\Python37\;C:\Python27\;C:\Python27\Scripts;C:\Perl64\site\bin;C:\Pe cmd ``` +[TOC](#TOC) +
+ +### Unix + +Exiv2 can be built on many Unix and Linux distros. We actively support the Unix Distributions NetBSD and FreeBSD + +#### NetBSD + +NetBSD uses pkgsrc as the package manager. You can build exiv2 with the commands: + +```bash +$ cd /usr/pkgsrc/graphics/exiv2 +$ make install +``` + +You can build exiv2 from source using the methods described for linux. I build and installed exiv2 using "Pure CMake" and didn't require conan. +You will want to use `pkgsrc` to build/install + +1) gcc (currently GCC 5.5.0)
+2) python3
+3) cmake
+4) bash
+5) sudo
+6) chksum +7) gettext
+ +I entered links into the file system `# ln -s /usr/pkg/bin/python37 /usr/local/bin/python3` and `# ln -s /usr/pkg/bin/bash /bin/bash` +It's important to ensure that `LD_LIBRARY_PATH` includes /usr/local/lib and /usr/pkg/lib. It's important to ensure that PATH includes `/usr/local/bin`, `/usr/pkg/bin` and`/usr/pkg/sbin`. + +#### FreeBSD + +FreeBSD uses pkg as the package manager. You should install the dependency expat. libz is already installed. As with NetBSD, you should use pkg to install python3, cmake, bash, sudo, gettext and gcc. The default GCC compiler is currently 8.3.0. + [TOC](#TOC) Written by Robin Mills
robin@clanmills.com
-Revised: 2019-04-28 \ No newline at end of file +Revised: 2019-05-09 \ No newline at end of file diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index b3290633..b5652cc8 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -35,7 +35,7 @@ /* Define to `const' or to empty, depending on the second argument of `iconv'. */ #cmakedefine ICONV_ACCEPTS_CONST_INPUT -#if defined ICONV_ACCEPTS_CONST_INPUT +#if defined(ICONV_ACCEPTS_CONST_INPUT) || defined(__NetBSD__) #define EXV_ICONV_CONST const #else #define EXV_ICONV_CONST diff --git a/cmake/packaging.cmake b/cmake/packaging.cmake index be292902..8535a95c 100644 --- a/cmake/packaging.cmake +++ b/cmake/packaging.cmake @@ -41,12 +41,19 @@ elseif ( APPLE ) set (PACKDIR Darwin) elseif ( LINUX ) set (PACKDIR Linux) +elseif ( CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) + set (PACKDIR Unix) else() - set (PACKDIR Linux) # unsupported systems such as FreeBSD + set (PACKDIR Linux) # Linux and unsupported systems +endif() + +set (BUNDLE_NAME ${PACKDIR}) +if ( CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) + set (BUNDLE_NAME ${CMAKE_SYSTEM_NAME}) endif() set (CC "") # Compiler -if ( NOT APPLE ) +if ( NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") set (CC Clang) endif() @@ -64,7 +71,11 @@ endif() set (VS "") # VisualStudio if ( MSVC ) - if ( MSVC_VERSION STREQUAL 1900 ) + if ( MSVC_VERSION STREQUAL 2100 ) + set(VS 2019) + elseif ( MSVC_VERSION STREQUAL 2000 ) + set(VS 2017) + elseif ( MSVC_VERSION STREQUAL 1900 ) set(VS 2015) elseif ( MSVC_VERSION STREQUAL 1800 ) set(VS 2013) @@ -77,7 +88,7 @@ if ( MSVC ) endif() endif() -set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${VS}${PACKDIR}${BS}${CC}${LT}${BT}${VI}${WR}) +set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${VS}${BUNDLE_NAME}${BS}${CC}${LT}${BT}${VI}${WR}) # https://stackoverflow.com/questions/17495906/copying-files-and-including-them-in-a-cpack-archive install(FILES "${PROJECT_SOURCE_DIR}/samples/exifprint.cpp" DESTINATION "samples") @@ -94,8 +105,14 @@ set( DOCS foreach(doc ${DOCS}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${doc} DESTINATION .) endforeach() -install(FILES ${PROJECT_SOURCE_DIR}/build/logs/build.txt DESTINATION "logs") -install(FILES ${PROJECT_SOURCE_DIR}/build/logs/test.txt DESTINATION "logs") + +# copy build/test logs which are only present on Jenkins builds +if(EXISTS ${PROJECT_SOURCE_DIR}/build/logs/build.txt) + install(FILES ${PROJECT_SOURCE_DIR}/build/logs/build.txt DESTINATION "logs") +endif() +if(EXISTS ${PROJECT_SOURCE_DIR}/build/logs/test.txt) + install(FILES ${PROJECT_SOURCE_DIR}/build/logs/test.txt DESTINATION "logs") +endif() # Copy releasenotes.txt and appropriate ReadMe.txt (eg releasenotes/${PACKDIR}/ReadMe.txt) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/releasenotes/${PACKDIR}/ReadMe.txt DESTINATION .) diff --git a/releasenotes/Unix/ReadMe.txt b/releasenotes/Unix/ReadMe.txt new file mode 100644 index 00000000..9466109d --- /dev/null +++ b/releasenotes/Unix/ReadMe.txt @@ -0,0 +1,59 @@ +Unix Exiv2 v0.27.1 Release Bundle (FreeBSD and NetBSD) +------------------------------------------------------ + +Structure of the bundle: +------------------------ + +bin/exiv2 exiv2 and sample applications +lib/libexiv2.so.0.27.1.0 & libexiv2-xmp.a libraries +lib/pkgconfig/exiv2.pc pkg-config file +lib/cmake/exiv2 CMake support/consume files +include/exiv2/ include files +share/man/ man pages +share/locale/ localisation files +samples/exifprint.cpp sample code +logs/ build and test logs + +ReadMe.txt This file +license.txt GPLv2.0 Software License +releasenotes.txt Late breaking news +README.md Developer Manual +README-CONAN.md Developer Manual Appendix +exiv2.png Exiv2 Logo + +To run exiv2 from the bundle +---------------------------- +$ cd +$ bin/exiv2 + +To build samples/exiftool.cpp from the bundle +--------------------------------------------- +$ g++ -std=c++98 samples/exifprint.cpp -L$PWD/lib -I$PWD/include -lexiv2 -o exifprint +$ env LD_LIBRARY_PATH="$PWD/lib:$LD_LIBRARY_PATH" ./exifprint + +To install for use by all users +------------------------------- +$ for i in bin include lib share ; do sudo mkdir -p /usr/local/$i ; sudo cp -R $i/* /usr/local/$i ; done + +To compile and link your own code using installed library and include files +--------------------------------------------------------------------------- +Method 1: Explicitly set include and linking options +$ cd +$ g++ -std=c++98 samples/exifprint.cpp -I/usr/local/include -L/usr/local/lib -lexiv2 -o exifprint +$ export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" +$ ./exifprint --version +exiv2=0.27.1 +... +xmlns=xmpidq:http://ns.adobe.com/xmp/Identifier/qual/1.0/ +$ + +Method 2: Use pkg-config to set include and linking options +$ cd +$ export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" +$ export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" +$ g++ -std=c++98 samples/exifprint.cpp -o exifprint $(pkg-config exiv2 --libs --cflags) +$ ./exifprint + +Method 3: Use the CMake support/consume files +See file: README.md Section: 2.6 "Consuming Exiv2 with CMake" + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0e989d2..1d0ccee4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -201,6 +201,10 @@ if (NOT MSVC) target_link_libraries( exiv2lib PRIVATE ${CMAKE_DL_LIBS}) # -ldl = dynamic loader used by src/version.cpp endif() + if ( CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) + target_link_libraries( exiv2lib PRIVATE -lprocstat) + endif() + if (CYGWIN OR MINGW OR MSYS) target_link_libraries( exiv2lib PRIVATE psapi ws2_32 ) endif() diff --git a/src/futils.cpp b/src/futils.cpp index 2de5dc00..b4c76234 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -22,6 +22,7 @@ #include "config.h" #include "futils.hpp" +#include "datasets.hpp" #include "enforce.hpp" // + standard includes @@ -48,6 +49,19 @@ #include #endif +#if defined(__FreeBSD__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + namespace Exiv2 { const char* ENVARDEF[] = {"/exiv2.php", "40"}; //!< @brief default URL for http exiv2 handler and time-out const char* ENVARKEY[] = {"EXIV2_HTTP_POST", "EXIV2_TIMEOUT"}; //!< @brief request keys for http exiv2 handler and time-out @@ -466,12 +480,22 @@ namespace Exiv2 { if (proc_pidpath (pid, pathbuf, sizeof(pathbuf)) > 0) { ret = pathbuf; } - #elif defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) + #elif defined(__FreeBSD__) + unsigned int n; + char buffer[PATH_MAX] = {}; + struct procstat* procstat = procstat_open_sysctl(); + struct kinfo_proc* procs = procstat ? procstat_getprocs(procstat, KERN_PROC_PID, getpid(), &n) : NULL; + if ( procs ) { + procstat_getpathname(procstat, procs, buffer, PATH_MAX); + ret = std::string(buffer); + } + // release resources + if ( procs ) procstat_freeprocs(procstat, procs); + if ( procstat ) procstat_close(procstat); + #elif defined(__unix__) // http://stackoverflow.com/questions/606041/how-do-i-get-the-path-of-a-process-in-unix-linux - char proc[100]; char path[500]; - sprintf(proc,"/proc/%d/exe", getpid()); - ssize_t l = readlink (proc, path,sizeof(path)-1); + ssize_t l = readlink ("/proc/self/exe", path,sizeof(path)-1); if (l>0) { path[l]=0; ret = path; diff --git a/src/version.cpp b/src/version.cpp index 80525b11..330023d6 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -55,6 +55,7 @@ #include #include #include +#include // #1147 #ifndef WIN32 @@ -114,23 +115,18 @@ namespace Exiv2 { #elif defined(__APPLE__) # include +#endif -#elif defined(__linux__) -# include -// http://syprog.blogspot.com/2011/12/listing-loaded-shared-objects-in-linux.html -# include - struct something - { - void* pointers[3]; - struct something* ptr; - }; - struct lmap - { - void* base_address; /* Base address of the shared object */ - char* path; /* Absolute file name (path) of the shared object */ - void* not_needed1; /* Pointer to the dynamic section of the shared object */ - struct lmap *next, *prev;/* chain of loaded objects */ - }; +#if defined(__FreeBSD__) +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif static bool shouldOutput(const exv_grep_keys_t& greps,const char* key,const std::string& value) @@ -247,6 +243,10 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) "mingw64"; #elif defined(__MINGW32__) "mingw32"; +#elif defined(__NetBSD__) + "netbsd"; +#elif defined(__FreeBSD__) + "freebsd"; #elif defined(__linux__) "linux"; #else @@ -260,6 +260,8 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) int have_iconv =0; int have_memory =0; int have_lstat =0; + int have_regex =0; + int have_regex_h =0; int have_stdbool =0; int have_stdint =0; int have_stdlib =0; @@ -279,7 +281,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) int have_sys_types =0; int have_unistd =0; int have_unicode_path=0; - int have_regex =0; int enable_video =0; int enable_webready =0; @@ -319,6 +320,14 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) have_lstat=1; #endif +#ifdef EXV_HAVE_REGEX + have_regex=1; +#endif + +#ifdef EXV_HAVE_REGEX_H + have_regex_h=1; +#endif + #ifdef EXV_HAVE_STDBOOL_H have_stdbool=1; #endif @@ -415,10 +424,13 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) use_ssh=1; #endif -#ifdef EXV_HAVE_REGEX_H - have_regex=1; -#endif +#define PUSH_PATH(path,libs,paths) \ + if ( Exiv2::fileExists(path,true) && paths.find(path) == paths.end() && path != "/" ) { \ + paths.insert(path); \ + libs.push_back(path); \ + } + Exiv2::StringSet paths; #if defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW__) // enumerate loaded libraries and determine path to executable HMODULE handles[200]; @@ -427,43 +439,49 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) char szFilename[_MAX_PATH]; for ( DWORD h = 0 ; h < cbNeeded/sizeof(handles[0]) ; h++ ) { GetModuleFileNameA(handles[h],szFilename,lengthof(szFilename)) ; - libs.push_back(szFilename); + std::string path(szFilename); + PUSH_PATH(path,libs,paths); } } #elif defined(__APPLE__) // man 3 dyld uint32_t count = _dyld_image_count(); for (uint32_t image = 0 ; image < count ; image++ ) { - const char* image_path = _dyld_get_image_name(image); - libs.push_back(image_path); + std::string path(_dyld_get_image_name(image)); + PUSH_PATH(path,libs,paths); } -#elif defined(__linux__) - // http://stackoverflow.com/questions/606041/how-do-i-get-the-path-of-a-process-in-unix-linux - char proc[100]; - char path[500]; - sprintf(proc,"/proc/%d/exe", getpid()); - int l = readlink (proc, path,sizeof(path)-1); - if (l>0) { - path[l]=0; - libs.push_back(path); - } else { - libs.push_back("unknown"); +#elif defined(__FreeBSD__) + unsigned int n; + struct procstat* procstat = procstat_open_sysctl(); + struct kinfo_proc* procs = procstat ? procstat_getprocs(procstat, KERN_PROC_PID, getpid(), &n) : NULL; + struct filestat_list* files = procs ? procstat_getfiles(procstat, procs, true) : NULL; + if ( files ) { + filestat* entry; + STAILQ_FOREACH(entry, files, next) { + std::string path(entry->fs_path); + PUSH_PATH(path,libs,paths); + } } - - // http://syprog.blogspot.com/2011/12/listing-loaded-shared-objects-in-linux.html - struct lmap* pl; - void* ph = dlopen(NULL, RTLD_NOW); - struct something* p = (struct something*) ph; - - p = p->ptr; - pl = (struct lmap*)p->ptr; - - while ( pl ) - { - libs.push_back(pl->path); - pl = pl->next; + // free resources + if ( files ) procstat_freefiles(procstat, files); + if ( procs ) procstat_freeprocs(procstat, procs); + if ( procstat ) procstat_close (procstat); + +#elif defined(__unix__) + // read file /proc/self/maps which has a list of files in memory + std::ifstream maps("/proc/self/maps",std::ifstream::in); + std::string string ; + while ( std::getline(maps,string) ) { + std::size_t pos = string.find_last_of(' '); + if ( pos != std::string::npos ) { + std::string path = string.substr(pos+1); + PUSH_PATH(path,libs,paths); + } } +#else + UNUSED(paths); #endif + output(os,keys,"exiv2",Exiv2::versionString()); output(os,keys,"platform" , platform ); output(os,keys,"compiler" , compiler ); @@ -505,6 +523,8 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) output(os,keys,"have_iconv" ,have_iconv ); output(os,keys,"have_memory" ,have_memory ); output(os,keys,"have_lstat" ,have_lstat ); + output(os,keys,"have_regex" ,have_regex ); + output(os,keys,"have_regex_h" ,have_regex_h ); output(os,keys,"have_stdbool" ,have_stdbool ); output(os,keys,"have_stdint" ,have_stdint ); output(os,keys,"have_stdlib" ,have_stdlib ); @@ -529,7 +549,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) output(os,keys,"enable_nls" ,enable_nls ); output(os,keys,"use_curl" ,use_curl ); output(os,keys,"use_ssh" ,use_ssh ); - output(os,keys,"have_regex" ,have_regex ); output(os,keys,"config_path" ,Exiv2::Internal::getExiv2ConfigPath()); @@ -551,10 +570,4 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys) output(os,keys,name,xmlns+":"+uri); } #endif - -#if defined(__linux__) - dlclose(ph); - ph=NULL; -#endif - } diff --git a/test/functions.source b/test/functions.source index a8cfe22b..3611c91a 100644 --- a/test/functions.source +++ b/test/functions.source @@ -421,7 +421,12 @@ checkSum() { # cygwin checksum: http://esrg.sourceforge.net/utils_win_up/md5sum/ # macosx - built/installed coreutils 8.25 http://ftp.gnu.org/gnu/coreutils/ - md5sum $1 | cut -d' ' -f 1 + platform=$(uname) + if [ "$platform" == 'NetBSD' -o "$platform" == 'FreeBSD' ]; then + md5 -q $1 + else + md5sum $1 | cut -d' ' -f 1 + fi } ##