From 33a924a07e76ffae86d2949581388768283f82b8 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 21:21:39 -0600 Subject: [PATCH 01/23] fix: ON_Material::MaxShine is not a function --- opennurbs_gl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opennurbs_gl.cpp b/opennurbs_gl.cpp index c47e625a..a649ddec 100644 --- a/opennurbs_gl.cpp +++ b/opennurbs_gl.cpp @@ -600,7 +600,7 @@ void ON_GL( const ON_Material* pMat ) ON_GL( pMat->Diffuse(), alpha, diffuse ); ON_GL( pMat->Specular(), alpha, specular ); ON_GL( pMat->Emission(), alpha, emission ); - GLint shine = (GLint)(128.0*(pMat->Shine() / ON_Material::MaxShine())); + GLint shine = (GLint)(128.0*(pMat->Shine() / ON_Material::MaxShine)); if ( shine == 0 ) { specular[0]=specular[1]=specular[2]=(GLfloat)0.0; } From d7554c79f8476fab994696540d3ac3af710ae7e2 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 21:27:14 -0600 Subject: [PATCH 02/23] feat: add CMake support for OpenNURBS --- CMakeLists.txt | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 9 +++++ 2 files changed, 105 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..a6f8a4e5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,96 @@ +cmake_minimum_required(VERSION 3.15) + +project(OpenNURBS CXX C) + +# OpenNURBS source +file(GLOB OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/*.h" + "${CMAKE_SOURCE_DIR}/*.cpp") + +# Build the opennurbs library +option(opennurbs_SHARED "Build shared libraries" OFF) +if(${opennurbs_SHARED}) + # if dynamic + + # Cannot build as shared library on Linux + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message( + FATAL_ERROR + "Building OpenNURBS as a shared library is not supported on Linux") + endif() + + # Generate a shared library + add_library(opennurbs SHARED ${OpenNURBS_SOURCE}) + set_target_properties(opennurbs PROPERTIES DEBUG_POSTFIX "d") + + # define opennurbs_EXPORTS + target_compile_definitions(opennurbs PRIVATE opennurbs_EXPORTS) +else() + # if static + + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + add_library(opennurbs STATIC ${OpenNURBS_SOURCE}) + else() + # Include UUID source (bundled with opennurbs) + file(GLOB UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/*.h" + "${CMAKE_SOURCE_DIR}/android_uuid/*.c") + list(REMOVE_ITEM UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/gen_uuid_nt.c") + + # Need to combine all source files for static linking on non-windows + add_library(opennurbs STATIC ${UUID_SRC} ${OpenNURBS_SOURCE}) + endif() +endif() + +# compile definitions +target_compile_definitions( + opennurbs + PRIVATE + ON_COMPILING_OPENNURBS + OPENNURBS_INPUT_LIBS_DIR="${CMAKE_CURRENT_BINARY_DIR}/$" + UNICODE) + +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + # Windows specific + + # Fix "WIN32" preprocessor definitions on x64 + if(${CMAKE_SIZEOF_VOID_P} EQUAL "8") + string(REPLACE "/DWIN32" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + target_compile_definitions(opennurbs PRIVATE WIN64) + endif() + +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Linux specific + + # Linux compiler definitions + target_compile_definitions(opennurbs PRIVATE ON_RUNTIME_LINUX + ON_CLANG_CONSTRUCTOR_BUG) +endif() + +# Dependencies + +# zlib +if(NOT ${opennurbs_ZLIB_LIB_DIR}) + # build zlib as static library (bundled with OpenNURBS) + file(GLOB ZLIB_SOURCE "${CMAKE_SOURCE_DIR}/zlib/*.h" + "${CMAKE_SOURCE_DIR}/zlib/*.c") + add_library(zlib STATIC ${ZLIB_SOURCE}) + target_compile_definitions(zlib PRIVATE MY_ZCALLOC Z_PREFIX) + target_compile_definitions( + opennurbs + PRIVATE + opennurbs_ZLIB_LIB_DIR="${CMAKE_CURRENT_BINARY_DIR}/$") +else() + target_compile_definitions( + opennurbs PRIVATE opennurbs_ZLIB_LIB_DIR=${opennurbs_ZLIB_LIB_DIR}) +endif() +# zlib-specific flags for opennurbs +target_compile_definitions(opennurbs PRIVATE MY_ZCALLOC Z_PREFIX) +target_link_libraries(opennurbs PRIVATE zlib) + +# shlwapi on windows +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries(opennurbs PRIVATE shlwapi) +endif() + +# Set the outputs of OpenNURBS CMake +set(OpenNURBS_LIBRARY ${opennurbs}) +set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") diff --git a/README.md b/README.md index d86b8177..9e198ead 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,15 @@ Please see ["Getting started"](https://developer.rhino3d.com/guides/opennurbs/ge There's also a collection of [example 3dm files](example_files/) available for testing. +# Building Using CMake: + +1. Clone the repository +2. `cd` to the root directory of the repository. +3. Run `cmake -S ./ -B ./build` to configure the CMake files. +Note: if [ninja-build](https://ninja-build.org/) is installed, use `cmake -S ./ -B ./build -G Ninja` to speed up the build speed. +4. Run `cmake --build ./build --config Release` to build the library. + + ## Questions? For technical support, please head over to [Discourse](https://discourse.mcneel.com/category/opennurbs). From dccb9345ed583bb03cba7dd83e30dfd0cefc6609 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 22:30:12 -0600 Subject: [PATCH 03/23] fix: add ON_COMPILER_CLANG for clang compiler --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f8a4e5..351aeaf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,11 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Linux specific # Linux compiler definitions - target_compile_definitions(opennurbs PRIVATE ON_RUNTIME_LINUX - ON_CLANG_CONSTRUCTOR_BUG) + target_compile_definitions(opennurbs PRIVATE ON_RUNTIME_LINUX) +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + target_compile_definitions(opennurbs PRIVATE ON_COMPILER_CLANG) endif() # Dependencies From 8bf554b04b0e951480a60379537745c9baf676eb Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 22:51:49 -0600 Subject: [PATCH 04/23] feat: add cross_dirent This adds the dirent library for windows + clang. https://github.com/tronkko/dirent --- CMakeLists.txt | 6 + cross_dirent/.gitignore | 24 + cross_dirent/ChangeLog | 129 +++++ cross_dirent/LICENSE | 21 + cross_dirent/README.md | 135 +++++ cross_dirent/cross_dirent.h | 11 + cross_dirent/include/dirent.h | 1027 +++++++++++++++++++++++++++++++++ 7 files changed, 1353 insertions(+) create mode 100644 cross_dirent/.gitignore create mode 100644 cross_dirent/ChangeLog create mode 100644 cross_dirent/LICENSE create mode 100644 cross_dirent/README.md create mode 100644 cross_dirent/cross_dirent.h create mode 100644 cross_dirent/include/dirent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 351aeaf7..3439e0c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") target_link_libraries(opennurbs PRIVATE shlwapi) endif() +# cross_dirent +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_include_directories( + opennurbs PRIVATE "${CMAKE_SOURCE_DIR}/cross_dirent/include/") +endif() + # Set the outputs of OpenNURBS CMake set(OpenNURBS_LIBRARY ${opennurbs}) set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") diff --git a/cross_dirent/.gitignore b/cross_dirent/.gitignore new file mode 100644 index 00000000..1e9efe31 --- /dev/null +++ b/cross_dirent/.gitignore @@ -0,0 +1,24 @@ +/CMakeCache.txt +/CMakeFiles +/CTestTestfile.cmake +/DartConfiguration.tcl +/Makefile +/Testing +/Win32 +/cmake_install.cmake +/find +/locate +/ls +/scandir +/cat +/t-compile +/t-dirent +/t-scandir +/t-cplusplus +/t-unicode +/t-strverscmp +/t-utf8 +/updatedb +/*.filters +/*.vcxproj +/*.dir diff --git a/cross_dirent/ChangeLog b/cross_dirent/ChangeLog new file mode 100644 index 00000000..d79cea25 --- /dev/null +++ b/cross_dirent/ChangeLog @@ -0,0 +1,129 @@ +2018-05-08 Toni Rönkkö + + * Version 1.23.2: fixes bad scandir prototype. + +2017-08-27 Toni Rönkkö + + * Version 1.23: support readdir_r and scandir functions. + +2017-07-18 Toni Rönkkö + + * Created release branches v1.22 and v1.21 to Git. Published version + 1.22 at softagalleria.net. + +2016-09-11 Toni Rönkkö + + * Version 1.22: added support for CMake. Thanks to Paul Fultz II. + +2014-09-25 Toni Rönkkö + + * Version 1.21: compiles correctly under Open Watcom. Thanks to + Virgil Banowetz for a patch! + +2014-04-07 Toni Rönkkö + + * Version 1.20.1: the zip file from the previous version did not open + correctly with Microsoft's compressed folders. Thanks to Alexandre + for info! + +2014-03-17 Toni Ronkko + + * Version 1.20: dirent.h compiles correctly in 64-bit architecture. + Thanks to Aaron Simmons! + +2014-03-03 Toni Ronkko + + * Version 1.13.2: define DT_LNK for compatibility with Unix + programs. Thanks to Joel Bruick for suggestion! + +2013-01-27 Toni Ronkko + + * Version 1.13.1: patch from Edward Berner fixes set_errno() on + Windows NT 4.0. + + * Revised wcstombs() and mbstowcs() wrappers to make sure that they do + not write past their target string. + + * PATH_MAX from windows.h includes zero terminator so there is no + need to add one extra byte to variables and structures. + +2012-12-12 Toni Ronkko + + * Version 1.13: use the traditional 8+3 file naming scheme if a file + name cannot be represented in the default ANSI code page. Now + compiles again with MSVC 6.0. Thanks to Konstantin Khomoutov for + testing. + +2012-10-01 Toni Ronkko + + * Version 1.12.1: renamed wide-character DIR structure _wDIR to + _WDIR (with capital W) in order to maintain compatibility with MingW. + +2012-09-30 Toni Ronkko + + * Version 1.12: define PATH_MAX and NAME_MAX. Added wide-character + variants _wDIR, _wdirent, _wopendir(), _wreaddir(), _wclosedir() and + _wrewinddir(). Thanks to Edgar Buerkle and Jan Nijtmans for ideas + and code. + + * Now avoiding windows.h. This allows dirent.h to be integrated + more easily into programs using winsock. Thanks to Fernando + Azaldegui. + +2011-03-15 Toni Ronkko + + * Version 1.11: defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. + +2010-08-11 Toni Ronkko + + * Version 1.10: added d_type and d_namlen fields to dirent structure. + The former is especially useful for determining whether directory + entry represents a file or a directory. For more information, see + http://www.delorie.com/gnu/docs/glibc/libc_270.html + + * Improved conformance to the standards. For example, errno is now + set properly on failure and assert() is never used. Thanks to Peter + Brockam for suggestions. + + * Fixed a bug in rewinddir(): when using relative directory names, + change of working directory no longer causes rewinddir() to fail. + +2009-12-15 John Cunningham + + * Version 1.9: added rewinddir member function + +2008-01-18 Toni Ronkko + + * Version 1.8: Using FindFirstFileA and WIN32_FIND_DATAA to avoid + converting string between multi-byte and unicode representations. + This makes the code simpler and also allows the code to be compiled + under MingW. Thanks to Azriel Fasten for the suggestion. + +2007-03-04 Toni Ronkko + + * Bug fix: due to the strncpy_s() function this file only compiled in + Visual Studio 2005. Using the new string functions only when the + compiler version allows. + +2006-11-02 Toni Ronkko + + * Major update: removed support for Watcom C, MS-DOS and Turbo C to + simplify the file, updated the code to compile cleanly on Visual + Studio 2005 with both unicode and multi-byte character strings, + removed rewinddir() as it had a bug. + +2006-08-20 Toni Ronkko + + * Removed all remarks about MSVC 1.0, which is antiqued now. + Simplified comments by removing SGML tags. + +2002-05-14 Toni Ronkko + + * Embedded the function definitions directly to the header so that no + source modules need to be included in the Visual Studio project. + Removed all the dependencies to other projects so that this header + file can be used independently. + +1998-05-28 Toni Ronkko + + * First version. diff --git a/cross_dirent/LICENSE b/cross_dirent/LICENSE new file mode 100644 index 00000000..af043606 --- /dev/null +++ b/cross_dirent/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 1998-2019 Toni Ronkko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/cross_dirent/README.md b/cross_dirent/README.md new file mode 100644 index 00000000..bd31abca --- /dev/null +++ b/cross_dirent/README.md @@ -0,0 +1,135 @@ +# Dirent + +Dirent is a C/C++ programming interface that allows programmers to retrieve +information about files and directories under Linux/UNIX. This project +provides Linux compatible Dirent interface for Microsoft Windows. + + +# How to Enable UTF-8 Support + +By default, Dirent functions expect the directory names to be represented in +the currently selected windows codepage. Moverover, Dirent functions return +file names in the presently selected codepage. If you wish to use UTF-8 file +names instead, then set the program's locale to ".utf8" or similar. For +example, your C main program might look like- + +``` +#include + +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, "LC_CTYPE=.utf8"); + + /*...*/ +} +``` + +For more information on UTF-8 support, please see setlocale in Visual Studio +[C runtime library reference](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-160#utf-8-support). + + +# Installation + +Download the latest Dirent installation package from +[GitHub](https://github.com/tronkko/dirent/releases) and +unpack the installation file with 7-zip, for example. The installation +package contains ``include/dirent.h`` file as well as a few example and test +programs. + + +## Installing Dirent for All Programs + +To make dirent.h available for all C/C++ programs, simply copy the +``include/dirent.h`` file to the system include directory. System include +directory contains header files such as ``assert.h`` and ``windows.h``. In +Visual Studio 2008, for example, the system include may be found at +``C:\Program Files\Microsoft Visual Studio 9.0\VC\include``. + +Everything you need is included in the single ``dirent.h`` file, and you can +start using Dirent immediately -- there is no need to add files to your +Visual Studio project. + + +## Embedding Dirent into Your Own Project + +If you wish to distribute ``dirent.h`` alongside with your own source code, +then copy ``include/dirent.h`` file to a new sub-directory within your project +and add that directory to include path on Windows while omitting the directory +under Linux/UNIX. This allows your project to be compiled against native +``dirent.h`` on Linux/UNIX while substituting the functionality on Microsoft +Windows. + + +## Examples + +The installation package contains six example programs: + +Program | Purpose +-------- | ----------------------------------------------------------------- +ls | List files in a directory, e.g. ls "c:\Program Files" +find | Find files in subdirectories, e.g. find "c:\Program Files\CMake" +updatedb | Build database of files in a drive, e.g. updatedb c:\ +locate | Locate a file from database, e.g. locate notepad +scandir | Demonstrate scandir() function +cat | Print a text file to screen + +Please install [CMake](https://cmake.org/) to build example and test programs. +Then, open command prompt and create a temporary directory ``c:\temp\dirent`` +for the build files as + +``` +c:\ +mkdir temp +mkdir temp\dirent +cd temp\dirent +``` + +Generate build files as + +``` +cmake d:\dirent +``` + +where ``d:\dirent`` is the root directory of the Dirent package (containing +this README.md file). If wish to omit example programs from the +build, then append the option ``-DDIRENT_BUILD_TESTS=OFF`` to the CMake +command line. + +Once CMake is finished, open Visual Studio, load the generated ``dirent.sln`` +file from the build directory and build the whole solution. Once the build +completes, run the example programs ls, find, updatedb and locate from the +command prompt as + +``` +cd Debug +ls . +find . +updatedb c:\ +locate cmd.exe +``` + +Visual Studio project also contains a solution named ``check`` which can be +used to verify that Dirent works as expected. Just build the solution from +Visual Studio to run the test programs. + + +# Contributing + +We love to receive contributions from you. See the +[CONTRIBUTING](CONTRIBUTING.md) file for details. + + +# Copying + +Dirent may be freely distributed under the MIT license. See the +[LICENSE](LICENSE) file for details. + + +# Alternatives to Dirent + +I ported Dirent to Microsoft Windows in 1998 when only a few alternatives +were available. However, the situation has changed since then and nowadays +both [Cygwin](http://www.cygwin.com) and [MingW](http://www.mingw.org) +allow you to compile a great number of UNIX programs in Microsoft Windows. +They both provide a full dirent API as well as many other UNIX APIs. MingW +can even be used for commercial applications! diff --git a/cross_dirent/cross_dirent.h b/cross_dirent/cross_dirent.h new file mode 100644 index 00000000..bc45af96 --- /dev/null +++ b/cross_dirent/cross_dirent.h @@ -0,0 +1,11 @@ +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + +// if not windows use the posix dirent.h +#include + +#else + +// use dirent windows +#include "./include/dirent.h" + +#endif \ No newline at end of file diff --git a/cross_dirent/include/dirent.h b/cross_dirent/include/dirent.h new file mode 100644 index 00000000..a2e847a0 --- /dev/null +++ b/cross_dirent/include/dirent.h @@ -0,0 +1,1027 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir(const char *dirname); +static _WDIR *_wopendir(const wchar_t *dirname); + +static struct dirent *readdir(DIR *dirp); +static struct _wdirent *_wreaddir(_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir(DIR *dirp); +static int _wclosedir(_WDIR *dirp); + +static void rewinddir(DIR* dirp); +static void _wrewinddir(_WDIR* dirp); + +static int scandir(const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort(const struct dirent **a, const struct dirent **b); + +static int versionsort(const struct dirent **a, const struct dirent **b); + +static int strverscmp(const char *a, const char *b); + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + +/* Compatibility with older Microsoft compilers and non-Microsoft compilers */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +# define wcstombs_s dirent_wcstombs_s +# define mbstowcs_s dirent_mbstowcs_s +#endif + +/* Optimize dirent_set_errno() away on modern Microsoft compilers */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define dirent_set_errno _set_errno +#endif + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_mbstowcs_s( + size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, + const char *mbstr, size_t count); +#endif + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_wcstombs_s( + size_t *pReturnValue, char *mbstr, size_t sizeInBytes, + const wchar_t *wcstr, size_t count); +#endif + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static void dirent_set_errno(int error); +#endif + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR *_wopendir(const wchar_t *dirname) +{ + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR)); + if (!dirp) + return NULL; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL); +#else + /* WinRT */ + size_t n = wcslen(dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt == NULL) + goto exit_closedir; + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); + if (n <= 0) + goto exit_closedir; +#else + /* WinRT */ + wcsncpy_s(dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first(dirp)) + goto exit_closedir; + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir(dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent *_wreaddir(_WDIR *dirp) +{ + /* + * Read directory entry to buffer. We can safely ignore the return + * value as entry will be set to NULL in case of error. + */ + struct _wdirent *entry; + (void) _wreaddir_r(dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result) +{ + /* Read next directory entry */ + WIN32_FIND_DATAW *datap = dirent_next(dirp); + if (!datap) { + /* Return NULL to indicate end of directory */ + *result = NULL; + return /*OK*/0; + } + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + size_t n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + DWORD attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + entry->d_type = DT_CHR; + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + entry->d_type = DT_DIR; + else + entry->d_type = DT_REG; + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct _wdirent); + + /* Set result address */ + *result = entry; + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int _wclosedir(_WDIR *dirp) +{ + if (!dirp) { + dirent_set_errno(EBADF); + return /*failure*/-1; + } + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + FindClose(dirp->handle); + + /* Release search pattern */ + free(dirp->patt); + + /* Release directory structure */ + free(dirp); + return /*success*/0; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void _wrewinddir(_WDIR* dirp) +{ + if (!dirp) + return; + + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + FindClose(dirp->handle); + + /* Open new search handle */ + dirent_first(dirp); +} + +/* Get first directory entry */ +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp) +{ + if (!dirp) + return NULL; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle == INVALID_HANDLE_VALUE) + goto error; + + /* A directory entry is now waiting in memory */ + dirp->cached = 1; + return &dirp->data; + +error: + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + + /* Set error code */ + DWORD errorcode = GetLastError(); + switch (errorcode) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno(EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno(ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno(ENOENT); + } + return NULL; +} + +/* Get next directory entry */ +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp) +{ + /* Is the next directory entry already in cache? */ + if (dirp->cached) { + /* Yes, a valid directory entry found in memory */ + dirp->cached = 0; + return &dirp->data; + } + + /* No directory entry in cache */ + if (dirp->handle == INVALID_HANDLE_VALUE) + return NULL; + + /* Read the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) == FALSE) + goto exit_close; + + /* Success */ + return &dirp->data; + + /* Failure */ +exit_close: + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + return NULL; +} + +/* Open directory stream using plain old C-string */ +static DIR *opendir(const char *dirname) +{ + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR)); + if (!dirp) + return NULL; + + /* Convert directory name to wide-character string */ + wchar_t wname[PATH_MAX + 1]; + size_t n; + int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1); + if (error) + goto exit_failure; + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (!dirp->wdirp) + goto exit_failure; + + /* Success */ + return dirp; + + /* Failure */ +exit_failure: + free(dirp); + return NULL; +} + +/* Read next directory entry */ +static struct dirent *readdir(DIR *dirp) +{ + /* + * Read directory entry to buffer. We can safely ignore the return + * value as entry will be set to NULL in case of error. + */ + struct dirent *entry; + (void) readdir_r(dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result) +{ + /* Read next directory entry */ + WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp); + if (!datap) { + /* No more directory entries */ + *result = NULL; + return /*OK*/0; + } + + /* Attempt to convert file name to multi-byte string */ + size_t n; + int error = wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, then + * attempt to use old 8+3 file name. This allows the program to + * access files although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file name + * unless the file system provides one. At least VirtualBox shared + * folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + DWORD attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + entry->d_type = DT_CHR; + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + entry->d_type = DT_DIR; + else + entry->d_type = DT_REG; + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof(struct dirent); + } else { + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + } + + /* Return pointer to directory entry */ + *result = entry; + return /*OK*/0; +} + +/* Close directory stream */ +static int closedir(DIR *dirp) +{ + int ok; + + if (!dirp) + goto exit_failure; + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + return ok; + +exit_failure: + /* Invalid directory stream */ + dirent_set_errno(EBADF); + return /*failure*/-1; +} + +/* Rewind directory stream to beginning */ +static void rewinddir(DIR* dirp) +{ + if (!dirp) + return; + + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); +} + +/* Scan directory for entries */ +static int scandir( + const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + int result; + + /* Open directory stream */ + DIR *dir = opendir(dirname); + if (!dir) { + /* Cannot open directory */ + return /*Error*/ -1; + } + + /* Read directory entries to memory */ + struct dirent *tmp = NULL; + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + while (1) { + /* Allocate room for a temporary directory entry */ + if (!tmp) { + tmp = (struct dirent*) malloc(sizeof(struct dirent)); + if (!tmp) + goto exit_failure; + } + + /* Read directory entry to temporary area */ + struct dirent *entry; + if (readdir_r(dir, tmp, &entry) != /*OK*/0) + goto exit_failure; + + /* Stop if we already read the last directory entry */ + if (entry == NULL) + goto exit_success; + + /* Determine whether to include the entry in results */ + if (filter && !filter(tmp)) + continue; + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + /* Compute number of entries in the new table */ + size_t num_entries = size * 2 + 16; + + /* Allocate new pointer table or enlarge existing */ + void *p = realloc(files, sizeof(void*) * num_entries); + if (!p) + goto exit_failure; + + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } + + /* Store the temporary entry to ptr table */ + files[size++] = tmp; + tmp = NULL; + } + +exit_failure: + /* Release allocated file entries */ + for (size_t i = 0; i < size; i++) { + free(files[i]); + } + + /* Release the pointer table */ + free(files); + files = NULL; + + /* Exit with error code */ + result = /*error*/ -1; + goto exit_status; + +exit_success: + /* Sort directory entries */ + qsort(files, size, sizeof(void*), + (int (*) (const void*, const void*)) compare); + + /* Pass pointer table to caller */ + if (namelist) + *namelist = files; + + /* Return the number of directory entries read */ + result = (int) size; + +exit_status: + /* Release temporary directory entry, if we had one */ + free(tmp); + + /* Close directory stream */ + closedir(dir); + return result; +} + +/* Alphabetical sorting */ +static int alphasort(const struct dirent **a, const struct dirent **b) +{ + return strcoll((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int versionsort(const struct dirent **a, const struct dirent **b) +{ + return strverscmp((*a)->d_name, (*b)->d_name); +} + +/* Compare strings */ +static int strverscmp(const char *a, const char *b) +{ + size_t i = 0; + size_t j; + + /* Find first difference */ + while (a[i] == b[i]) { + if (a[i] == '\0') { + /* No difference */ + return 0; + } + ++i; + } + + /* Count backwards and find the leftmost digit */ + j = i; + while (j > 0 && isdigit(a[j-1])) { + --j; + } + + /* Determine mode of comparison */ + if (a[j] == '0' || b[j] == '0') { + /* Find the next non-zero digit */ + while (a[j] == '0' && a[j] == b[j]) { + j++; + } + + /* String with more digits is smaller, e.g 002 < 01 */ + if (isdigit(a[j])) { + if (!isdigit(b[j])) { + return -1; + } + } else if (isdigit(b[j])) { + return 1; + } + } else if (isdigit(a[j]) && isdigit(b[j])) { + /* Numeric comparison */ + size_t k1 = j; + size_t k2 = j; + + /* Compute number of digits in each string */ + while (isdigit(a[k1])) { + k1++; + } + while (isdigit(b[k2])) { + k2++; + } + + /* Number with more digits is bigger, e.g 999 < 1000 */ + if (k1 < k2) + return -1; + else if (k1 > k2) + return 1; + } + + /* Alphabetical comparison */ + return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]); +} + +/* Convert multi-byte string to wide character string */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_mbstowcs_s( + size_t *pReturnValue, wchar_t *wcstr, + size_t sizeInWords, const char *mbstr, size_t count) +{ + /* Older Visual Studio or non-Microsoft compiler */ + size_t n = mbstowcs(wcstr, mbstr, sizeInWords); + if (wcstr && n >= count) + return /*error*/ 1; + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) + n = sizeInWords - 1; + wcstr[n] = 0; + } + + /* Length of multi-byte string with zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + return 0; +} +#endif + +/* Convert wide-character string to multi-byte string */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static int dirent_wcstombs_s( + size_t *pReturnValue, char *mbstr, + size_t sizeInBytes, const wchar_t *wcstr, size_t count) +{ + /* Older Visual Studio or non-Microsoft compiler */ + size_t n = wcstombs(mbstr, wcstr, sizeInBytes); + if (mbstr && n >= count) + return /*error*/1; + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + return 0; +} +#endif + +/* Set errno variable */ +#if !defined(_MSC_VER) || _MSC_VER < 1400 +static void dirent_set_errno(int error) +{ + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; +} +#endif + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ From 1a14cc0eb7f177ce8aed9a1a8b9e7d3b0df527b8 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 22:58:40 -0600 Subject: [PATCH 05/23] fix: add uuid.h requirement for the clang compiler on windows --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3439e0c9..c1e98c2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") string(REPLACE "/DWIN32" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") target_compile_definitions(opennurbs PRIVATE WIN64) endif() - elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Linux specific @@ -100,6 +99,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") opennurbs PRIVATE "${CMAKE_SOURCE_DIR}/cross_dirent/include/") endif() +# uuid on non-linux/android - clang +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # uuid/uuid.h is required by opennurbs + find_package(uuid REQUIRED) + target_include_directories(opennurbs PRIVATE ${uuid_INCLUDE_DIRS}) +endif() + # Set the outputs of OpenNURBS CMake set(OpenNURBS_LIBRARY ${opennurbs}) set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") From 190aab02dc7ff505920ebdc1c239c9046777c023 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 23:15:21 -0600 Subject: [PATCH 06/23] fix: fix building opennurbs_lock.h --- opennurbs_lock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opennurbs_lock.h b/opennurbs_lock.h index a428c857..4902d938 100644 --- a/opennurbs_lock.h +++ b/opennurbs_lock.h @@ -112,8 +112,8 @@ class ON_CLASS ON_Lock // needs to have dll-interface to be used by clients of class 'ON_Lock' // m_lock_value is private and all code that manages m_lock_value is explicitly implemented in the DLL. private: -#if defined(ON_COMPILER_CLANG) - std::atomic m_lock_value; +#if defined(ON_CLANG_CONSTRUCTOR_BUG_INIT) + std::atomic m_lock_value; #else std::atomic m_lock_value = ON_Lock::UnlockedValue; #endif From 1845712902090925b059ada3a7046505604e471b Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 23:23:57 -0600 Subject: [PATCH 07/23] fix: handle opengl dependency Update CMakeLists.txt --- CMakeLists.txt | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1e98c2e..2ec57e8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,21 @@ project(OpenNURBS CXX C) file(GLOB OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/*.h" "${CMAKE_SOURCE_DIR}/*.cpp") +# OpenGL dependency +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + list(REMOVE_ITEM OpenNURBS_SOURCE + "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp932.cpp") + list(REMOVE_ITEM OpenNURBS_SOURCE + "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") +endif() + +# remove opennurbs_gl if no opengl +find_package(OpenGL) +if(NOT OPENGL_FOUND) + message(WARNING "OpenGL not found. Excluding opennurbs_gl") + list(REMOVE_ITEM OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_gl.cpp") +endif() + # Build the opennurbs library option(opennurbs_SHARED "Build shared libraries" OFF) if(${opennurbs_SHARED}) @@ -100,12 +115,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") endif() # uuid on non-linux/android - clang -if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID MATCHES + ".*Clang") # uuid/uuid.h is required by opennurbs find_package(uuid REQUIRED) target_include_directories(opennurbs PRIVATE ${uuid_INCLUDE_DIRS}) endif() +# OpenGL +if(OPENGL_FOUND) + target_link_libraries(opennurbs PRIVATE ${OpenGL_LIBRARIES}) +endif() + # Set the outputs of OpenNURBS CMake set(OpenNURBS_LIBRARY ${opennurbs}) set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") From 8d68223690e64c3e67c6dc41e4f19cc2bbd17854 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 23:39:15 -0600 Subject: [PATCH 08/23] fix: fix default constructor issue on linux gcc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes ``` /home/aminya/opennurbs/opennurbs_statics.cpp:747:21: error: uninitialized const ‘ON_AngleValue::Unset’ [-fpermissive] 747 | const ON_AngleValue ON_AngleValue::Unset ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_AngleValue); | ^~~~~~~~~~~~~ In file included from /home/aminya/opennurbs/opennurbs.h:81, from /home/aminya/opennurbs/opennurbs_statics.cpp:1: /home/aminya/opennurbs/opennurbs_string_value.h:274:16: note: ‘const class ON_AngleValue’ has no user-provided default constructor 274 | class ON_CLASS ON_AngleValue | ^~~~~~~~~~~~~ /home/aminya/opennurbs/opennurbs_string_value.h:277:3: note: constructor is not user-provided because it is explicitly defaulted in the class body 277 | ON_AngleValue() = default; | ^~~~~~~~~~~~~ ``` --- opennurbs_statics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opennurbs_statics.cpp b/opennurbs_statics.cpp index bc23eb8f..075a3d9d 100644 --- a/opennurbs_statics.cpp +++ b/opennurbs_statics.cpp @@ -515,7 +515,7 @@ static ON_SHA1_Hash ON_SHA1_Hash_EmptyContentHash() const ON_SHA1_Hash ON_SHA1_Hash::EmptyContentHash = ON_SHA1_Hash_EmptyContentHash(); const ON_SHA1_Hash ON_SHA1_Hash::ZeroDigest ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_SHA1_Hash); -const ONX_ModelTest ONX_ModelTest::Unset ON_CLANG_CONSTRUCTOR_BUG_INIT(ONX_ModelTest); +const ONX_ModelTest ONX_ModelTest::Unset = ONX_ModelTest(); // Works with Microsoft's CL, fails for Apple's CLang //// const struct ON_UnicodeErrorParameters ON_UnicodeErrorParameters::MaskErrors = { 0, 0xFFFFFFFF, ON_UnicodeCodePoint::ON_ReplacementCharacter }; @@ -744,7 +744,7 @@ const ON_AngleUnitName ON_AngleUnitName::None ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_A const ON_LengthValue ON_LengthValue::Unset ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_LengthValue); const ON_LengthValue ON_LengthValue::Zero = ON_LengthValue::Create(0.0, ON::LengthUnitSystem::None, 0, ON_LengthValue::StringFormat::CleanDecimal); -const ON_AngleValue ON_AngleValue::Unset ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_AngleValue); +const ON_AngleValue ON_AngleValue::Unset = ON_AngleValue(); const ON_AngleValue ON_AngleValue::Zero = ON_AngleValue::Create(0.0, ON::AngleUnitSystem::None, 0, ON_AngleValue::StringFormat::CleanDecimal ); const ON_ScaleValue ON_ScaleValue::Unset ON_CLANG_CONSTRUCTOR_BUG_INIT(ON_ScaleValue); From 7876620fe2777133edc9a7632ddac2e0c777d313 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 15 Nov 2021 23:39:35 -0600 Subject: [PATCH 09/23] fix: exclude opennurbs_unicode_cp932 and 949 on non-windows --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ec57e8d..f1dea054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,13 @@ project(OpenNURBS CXX C) file(GLOB OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/*.h" "${CMAKE_SOURCE_DIR}/*.cpp") +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + list(REMOVE_ITEM OpenNURBS_SOURCE + "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp932.cpp") + list(REMOVE_ITEM OpenNURBS_SOURCE + "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") +endif() + # OpenGL dependency if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") list(REMOVE_ITEM OpenNURBS_SOURCE From e0a1f330b2b0fa48f0af0498ad589eab9b06a602 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Tue, 16 Nov 2021 10:21:12 -0600 Subject: [PATCH 10/23] fix: fix zlib build in the shared mode --- CMakeLists.txt | 41 +++++++++++++++++++++++------------------ README.md | 22 +++++++++++++++++++--- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1dea054..f26a7988 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,16 +33,8 @@ option(opennurbs_SHARED "Build shared libraries" OFF) if(${opennurbs_SHARED}) # if dynamic - # Cannot build as shared library on Linux - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - message( - FATAL_ERROR - "Building OpenNURBS as a shared library is not supported on Linux") - endif() - - # Generate a shared library + # opennurbs shared library add_library(opennurbs SHARED ${OpenNURBS_SOURCE}) - set_target_properties(opennurbs PROPERTIES DEBUG_POSTFIX "d") # define opennurbs_EXPORTS target_compile_definitions(opennurbs PRIVATE opennurbs_EXPORTS) @@ -92,23 +84,29 @@ endif() # Dependencies # zlib -if(NOT ${opennurbs_ZLIB_LIB_DIR}) - # build zlib as static library (bundled with OpenNURBS) +option(opennurbs_EXTERNAL_ZLIB, "use external zlib package" OFF) +if(${opennurbs_EXTERNAL_ZLIB} OR ${opennurbs_ZLIB_LIB_DIR}) + message(STATUS "Using external ZLIB") + find_package(ZLIB REQUIRED) + target_link_libraries(opennurbs PRIVATE ZLIB::ZLIB) + target_compile_definitions(ZLIB::ZLIB PRIVATE MY_ZCALLOC Z_PREFIX) + get_target_property(opennurbs_ZLIB_LIB_DIR ZLIB::ZLIB + LIBRARY_OUTPUT_DIRECTORY) + target_compile_definitions( + opennurbs PRIVATE opennurbs_ZLIB_LIB_DIR="${opennurbs_ZLIB_LIB_DIR}") +else() + # build zlib (bundled with OpenNURBS) file(GLOB ZLIB_SOURCE "${CMAKE_SOURCE_DIR}/zlib/*.h" "${CMAKE_SOURCE_DIR}/zlib/*.c") - add_library(zlib STATIC ${ZLIB_SOURCE}) + add_library(zlib ${ZLIB_SOURCE}) target_compile_definitions(zlib PRIVATE MY_ZCALLOC Z_PREFIX) - target_compile_definitions( - opennurbs - PRIVATE - opennurbs_ZLIB_LIB_DIR="${CMAKE_CURRENT_BINARY_DIR}/$") -else() + set(opennurbs_ZLIB_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/$") target_compile_definitions( opennurbs PRIVATE opennurbs_ZLIB_LIB_DIR=${opennurbs_ZLIB_LIB_DIR}) + target_link_libraries(opennurbs PRIVATE zlib) endif() # zlib-specific flags for opennurbs target_compile_definitions(opennurbs PRIVATE MY_ZCALLOC Z_PREFIX) -target_link_libraries(opennurbs PRIVATE zlib) # shlwapi on windows if(CMAKE_SYSTEM_NAME STREQUAL "Windows") @@ -134,6 +132,13 @@ if(OPENGL_FOUND) target_link_libraries(opennurbs PRIVATE ${OpenGL_LIBRARIES}) endif() +# Suppress -Wdefaulted-function-deleted on Clang +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + # TODO fix this + message(WARNING "Suppressing -Wdefaulted-function-deleted for opennurbs") + target_compile_options(opennurbs PRIVATE -Wno-defaulted-function-deleted) +endif() + # Set the outputs of OpenNURBS CMake set(OpenNURBS_LIBRARY ${opennurbs}) set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") diff --git a/README.md b/README.md index 9e198ead..f9123a2f 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,25 @@ There's also a collection of [example 3dm files](example_files/) available for t 1. Clone the repository 2. `cd` to the root directory of the repository. -3. Run `cmake -S ./ -B ./build` to configure the CMake files. -Note: if [ninja-build](https://ninja-build.org/) is installed, use `cmake -S ./ -B ./build -G Ninja` to speed up the build speed. -4. Run `cmake --build ./build --config Release` to build the library. +3. Run the following to configure the CMake files. +``` +cmake -S ./ -B ./build +``` + + Note: if [ninja-build](https://ninja-build.org/) is installed, you can specify `Ninja` to speed up the build: + ``` + cmake -S ./ -B ./build -G Ninja + ``` + + Note: To use Ninja with the Visual Studio Compiler, open the MSVC command prompt (or run `vcvarsall.bat`), and run: + ``` + cmake -S ./ -B ./build -G "Ninja Multi-Config" -D CMAKE_CXX_COMPILER=cl -D CMAKE_C_COMPILER=cl + ``` + +4. Finally, run the following to build the library. +``` +cmake --build ./build --config Release +``` ## Questions? From 3e35580dc4889a47cd57693ae6936ff6f72da227 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 09:58:51 -0600 Subject: [PATCH 11/23] fix: use unsigned int so that 0xFFFFFFFF can be stored --- opennurbs_defines.h | 4 ++-- opennurbs_object_history.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opennurbs_defines.h b/opennurbs_defines.h index fa156bae..35e2e0cf 100644 --- a/opennurbs_defines.h +++ b/opennurbs_defines.h @@ -2133,7 +2133,7 @@ class ON_CLASS ON // the values. The reason for the gaps between the enum // values is to leave room for future snaps with prededence // falling between existing snaps - enum osnap_mode + enum osnap_mode: unsigned int { os_none = 0, os_near = 2, @@ -2409,7 +2409,7 @@ class ON_CLASS ON_COMPONENT_INDEX // Do not change these values; they are stored in 3dm archives // and provide a persistent way to indentify components of // complex objects. - enum TYPE + enum TYPE: unsigned int { invalid_type = 0, diff --git a/opennurbs_object_history.cpp b/opennurbs_object_history.cpp index a3d06de4..fd77eaee 100644 --- a/opennurbs_object_history.cpp +++ b/opennurbs_object_history.cpp @@ -31,7 +31,7 @@ class ON_Value // The VALUE_TYPE enum values must never be changed // because the values are used to determine the parameter // type during file reading. Additions can be made. - enum VALUE_TYPE + enum VALUE_TYPE: unsigned int { no_value_type = 0, From 39f967a21cb2e8d6f4464ac1d0ddd98fbbde2f9d Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 10:23:46 -0600 Subject: [PATCH 12/23] fix: fix building with clang on Windows --- CMakeLists.txt | 7 ++++--- opennurbs_locale.cpp | 8 ++++---- opennurbs_string_format.cpp | 4 ++-- opennurbs_string_scan.cpp | 6 +++--- opennurbs_system.h | 2 ++ 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f26a7988..f7857655 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,9 +119,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") opennurbs PRIVATE "${CMAKE_SOURCE_DIR}/cross_dirent/include/") endif() -# uuid on non-linux/android - clang -if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID MATCHES - ".*Clang") +# uuid with clang on non-linux, android, windows +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" + AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows" + AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # uuid/uuid.h is required by opennurbs find_package(uuid REQUIRED) target_include_directories(opennurbs PRIVATE ${uuid_INCLUDE_DIRS}) diff --git a/opennurbs_locale.cpp b/opennurbs_locale.cpp index 45c46a5b..92e50e19 100644 --- a/opennurbs_locale.cpp +++ b/opennurbs_locale.cpp @@ -1343,7 +1343,7 @@ class ON_CRT_LOCALE static bool Validate_sprintf_l() { -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) // Test formatted printing char buffer[64] = { 0 }; @@ -1368,7 +1368,7 @@ class ON_CRT_LOCALE static bool Validate_sprintf_s_l() { -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) // Test formatted printing char buffer[64] = { 0 }; @@ -1422,7 +1422,7 @@ class ON_CRT_LOCALE static bool Validate_sscanf_l() { -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) // Test formatted scanning double a = ON_UNSET_VALUE; @@ -1447,7 +1447,7 @@ class ON_CRT_LOCALE static bool Validate_sscanf_s_l() { -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) // Test formatted scanning double a = ON_UNSET_VALUE; diff --git a/opennurbs_string_format.cpp b/opennurbs_string_format.cpp index 304b351e..8dd6e158 100644 --- a/opennurbs_string_format.cpp +++ b/opennurbs_string_format.cpp @@ -803,7 +803,7 @@ int ON_String::FormatVargsIntoBuffer( if (0 == buffer || buffer_capacity <= 0) return -1; buffer[0] = 0; -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) // CLang modifies args so a copy is required va_list args_copy; va_copy (args_copy, args); @@ -854,7 +854,7 @@ int ON_String::FormatVargsOutputCount( if ( nullptr == format || 0 == format[0] ) return 0; -#if defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU) +#if (defined(ON_COMPILER_CLANG) || defined(ON_COMPILER_GNU)) && !defined(ON_RUNTIME_WIN) // CLang modifies args so a copy is required va_list args_copy; va_copy (args_copy, args); diff --git a/opennurbs_string_scan.cpp b/opennurbs_string_scan.cpp index 34df9069..efe90f93 100644 --- a/opennurbs_string_scan.cpp +++ b/opennurbs_string_scan.cpp @@ -85,7 +85,7 @@ int ON_String::ScanBufferVargs( va_list args ) { -#if defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX) +#if (defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) if (nullptr == buffer || nullptr == format) return -1; @@ -398,7 +398,7 @@ const char* ON_String::ToNumber( local_buffer[local_buffer_count++] = 0; double x = value_on_failure; -#if defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX) +#if (defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) if (1 == sscanf(local_buffer, "%lg", &x)) { @@ -660,7 +660,7 @@ const wchar_t* ON_wString::ToNumber( local_buffer[local_buffer_count++] = 0; double x = value_on_failure; -#if defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX) +#if (defined(ON_COMPILER_CLANG) || defined(ON_RUNTIME_LINUX)) && !defined(ON_RUNTIME_WIN) #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) if (1 == sscanf(local_buffer, "%lg", &x)) { diff --git a/opennurbs_system.h b/opennurbs_system.h index 504fea2f..a92eb9a8 100644 --- a/opennurbs_system.h +++ b/opennurbs_system.h @@ -542,6 +542,8 @@ typedef ON__UINT32 wchar_t; #pragma ON_PRAGMA_WARNING_BEFORE_DIRTY_INCLUDE #if defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) #include "android_uuid/uuid.h" +#elif defined(ON_RUNTIME_WIN) +#include #else #include #endif From 3122683bdf8e73f3a2f5cb654a9c2ab42bc0e478 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 10:39:04 -0600 Subject: [PATCH 13/23] fix: specify the output directory for zlib --- CMakeLists.txt | 5 ++++- README.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7857655..d0f13550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,9 @@ else() "${CMAKE_SOURCE_DIR}/zlib/*.c") add_library(zlib ${ZLIB_SOURCE}) target_compile_definitions(zlib PRIVATE MY_ZCALLOC Z_PREFIX) + set_target_properties( + zlib PROPERTIES ARCHIVE_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}/$") set(opennurbs_ZLIB_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/$") target_compile_definitions( opennurbs PRIVATE opennurbs_ZLIB_LIB_DIR=${opennurbs_ZLIB_LIB_DIR}) @@ -119,7 +122,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") opennurbs PRIVATE "${CMAKE_SOURCE_DIR}/cross_dirent/include/") endif() -# uuid with clang on non-linux, android, windows +# uuid with clang on non-linux, android, windows if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") diff --git a/README.md b/README.md index f9123a2f..4563f568 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ cmake -S ./ -B ./build Note: if [ninja-build](https://ninja-build.org/) is installed, you can specify `Ninja` to speed up the build: ``` - cmake -S ./ -B ./build -G Ninja + cmake -S ./ -B ./build -G "Ninja Multi-Config" ``` Note: To use Ninja with the Visual Studio Compiler, open the MSVC command prompt (or run `vcvarsall.bat`), and run: From 10757b52991636298c44c4b0a709206df587408c Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 11:36:39 -0600 Subject: [PATCH 14/23] fix: use lower case opennurbs and upper case for options --- CMakeLists.txt | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0f13550..b626a4b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,23 @@ cmake_minimum_required(VERSION 3.15) -project(OpenNURBS CXX C) +project(opennurbs CXX C) -# OpenNURBS source -file(GLOB OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/*.h" +# opennurbs source +file(GLOB opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/*.h" "${CMAKE_SOURCE_DIR}/*.cpp") if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - list(REMOVE_ITEM OpenNURBS_SOURCE + list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp932.cpp") - list(REMOVE_ITEM OpenNURBS_SOURCE + list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") endif() # OpenGL dependency if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - list(REMOVE_ITEM OpenNURBS_SOURCE + list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp932.cpp") - list(REMOVE_ITEM OpenNURBS_SOURCE + list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") endif() @@ -25,16 +25,16 @@ endif() find_package(OpenGL) if(NOT OPENGL_FOUND) message(WARNING "OpenGL not found. Excluding opennurbs_gl") - list(REMOVE_ITEM OpenNURBS_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_gl.cpp") + list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_gl.cpp") endif() # Build the opennurbs library -option(opennurbs_SHARED "Build shared libraries" OFF) -if(${opennurbs_SHARED}) +option({OPENNURBS_SHARED "Build shared libraries" OFF) +if(${OPENNURBS_SHARED}) # if dynamic # opennurbs shared library - add_library(opennurbs SHARED ${OpenNURBS_SOURCE}) + add_library(opennurbs SHARED ${opennurbs_SOURCE}) # define opennurbs_EXPORTS target_compile_definitions(opennurbs PRIVATE opennurbs_EXPORTS) @@ -42,7 +42,7 @@ else() # if static if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - add_library(opennurbs STATIC ${OpenNURBS_SOURCE}) + add_library(opennurbs STATIC ${opennurbs_SOURCE}) else() # Include UUID source (bundled with opennurbs) file(GLOB UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/*.h" @@ -50,7 +50,7 @@ else() list(REMOVE_ITEM UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/gen_uuid_nt.c") # Need to combine all source files for static linking on non-windows - add_library(opennurbs STATIC ${UUID_SRC} ${OpenNURBS_SOURCE}) + add_library(opennurbs STATIC ${UUID_SRC} ${opennurbs_SOURCE}) endif() endif() @@ -84,18 +84,18 @@ endif() # Dependencies # zlib -option(opennurbs_EXTERNAL_ZLIB, "use external zlib package" OFF) -if(${opennurbs_EXTERNAL_ZLIB} OR ${opennurbs_ZLIB_LIB_DIR}) +option({OPENNURBS_EXTERNAL_ZLIB, "use external zlib package" OFF) +if(${OPENNURBS_EXTERNAL_ZLIB} OR ${OPENNURBS_ZLIB_LIB_DIR}) message(STATUS "Using external ZLIB") find_package(ZLIB REQUIRED) target_link_libraries(opennurbs PRIVATE ZLIB::ZLIB) target_compile_definitions(ZLIB::ZLIB PRIVATE MY_ZCALLOC Z_PREFIX) - get_target_property(opennurbs_ZLIB_LIB_DIR ZLIB::ZLIB + get_target_property(OPENNURBS_ZLIB_LIB_DIR ZLIB::ZLIB LIBRARY_OUTPUT_DIRECTORY) target_compile_definitions( - opennurbs PRIVATE opennurbs_ZLIB_LIB_DIR="${opennurbs_ZLIB_LIB_DIR}") + opennurbs PRIVATE OPENNURBS_ZLIB_LIB_DIR="${OPENNURBS_ZLIB_LIB_DIR}") else() - # build zlib (bundled with OpenNURBS) + # build zlib (bundled with opennurbs) file(GLOB ZLIB_SOURCE "${CMAKE_SOURCE_DIR}/zlib/*.h" "${CMAKE_SOURCE_DIR}/zlib/*.c") add_library(zlib ${ZLIB_SOURCE}) @@ -143,6 +143,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") target_compile_options(opennurbs PRIVATE -Wno-defaulted-function-deleted) endif() -# Set the outputs of OpenNURBS CMake -set(OpenNURBS_LIBRARY ${opennurbs}) -set(OpenNURBS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") +# Set the outputs of opennurbs CMake +set(opennurbs_LIBRARY ${opennurbs}) +set(opennurbs_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") From 126f16f5731495e513fa9111408919e0fbabd462 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 13:40:48 -0600 Subject: [PATCH 15/23] fix: fix opennurbs_INCLUDE_DIR --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b626a4b1..580f53bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,4 +145,4 @@ endif() # Set the outputs of opennurbs CMake set(opennurbs_LIBRARY ${opennurbs}) -set(opennurbs_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/opennurbs") +set(opennurbs_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}") From ba973880b019db9b60d33a3ac0bace8e1fbca6a7 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 16:31:27 -0600 Subject: [PATCH 16/23] fix: fix building as a shared library with MSVC --- CMakeLists.txt | 31 ++++++++++++++++--------------- README.md | 21 ++++++++++++++++++++- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 580f53bc..d569fa82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,31 +13,30 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") endif() -# OpenGL dependency -if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - list(REMOVE_ITEM opennurbs_SOURCE - "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp932.cpp") - list(REMOVE_ITEM opennurbs_SOURCE - "${CMAKE_SOURCE_DIR}/opennurbs_unicode_cp949.cpp") -endif() - # remove opennurbs_gl if no opengl find_package(OpenGL) -if(NOT OPENGL_FOUND) +if(NOT ${OPENGL_FOUND}) message(WARNING "OpenGL not found. Excluding opennurbs_gl") list(REMOVE_ITEM opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/opennurbs_gl.cpp") endif() # Build the opennurbs library -option({OPENNURBS_SHARED "Build shared libraries" OFF) +option(OPENNURBS_SHARED "Build shared libraries" OFF) if(${OPENNURBS_SHARED}) # if dynamic # opennurbs shared library add_library(opennurbs SHARED ${opennurbs_SOURCE}) - # define opennurbs_EXPORTS - target_compile_definitions(opennurbs PRIVATE opennurbs_EXPORTS) + # define opennurbs_EXPORTS to compile as a shared library + target_compile_definitions(opennurbs PRIVATE OPENNURBS_EXPORTS + ON_COMPILING_OPENNURBS) + + # define OPENNURBS_IMORTS for the usage of the library + message( + WARNING + "Define `OPENNURBS_IMORTS` when using the opennurbs.dll before including opennurbs_public.h\n target_compile_definitions(main PUBLIC OPENNURBS_IMPORTS)" + ) else() # if static @@ -52,13 +51,15 @@ else() # Need to combine all source files for static linking on non-windows add_library(opennurbs STATIC ${UUID_SRC} ${opennurbs_SOURCE}) endif() + + # define ON_COMPILING_OPENNURBS to compile as a static library + target_compile_definitions(opennurbs PRIVATE ON_COMPILING_OPENNURBS) endif() # compile definitions target_compile_definitions( opennurbs PRIVATE - ON_COMPILING_OPENNURBS OPENNURBS_INPUT_LIBS_DIR="${CMAKE_CURRENT_BINARY_DIR}/$" UNICODE) @@ -132,8 +133,8 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" endif() # OpenGL -if(OPENGL_FOUND) - target_link_libraries(opennurbs PRIVATE ${OpenGL_LIBRARIES}) +if(${OPENGL_FOUND}) + target_link_libraries(opennurbs PRIVATE OpenGL::GL OpenGL::GLU) endif() # Suppress -Wdefaulted-function-deleted on Clang diff --git a/README.md b/README.md index 4563f568..69f5dafd 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Please see ["Getting started"](https://developer.rhino3d.com/guides/opennurbs/ge There's also a collection of [example 3dm files](example_files/) available for testing. -# Building Using CMake: +## Building Using CMake: 1. Clone the repository 2. `cd` to the root directory of the repository. @@ -52,6 +52,25 @@ cmake -S ./ -B ./build cmake --build ./build --config Release ``` +### Build as a shared library with CMake + +To build as a DLL with Visual Studio, you should add `-DOPENNURBS_SHARED=ON` to the command of step `3`: +``` +cmake -S ./ -B ./build -DOPENNURBS_SHARED=ON +``` + +or with Ninja +``` +cmake -S ./ -B ./build -G "Ninja Multi-Config" -D CMAKE_CXX_COMPILER=cl -D CMAKE_C_COMPILER=cl -DOPENNURBS_SHARED=ON +``` + +Build as usual as we described in step 4. + +When using the dll, define `OPENNURBS_IMPORTS` before including `opennurbs_public.h` +```cmake +target_compile_definitions(main PUBLIC OPENNURBS_IMPORTS) +``` + ## Questions? From cb2a1e50674d8073f6dea4cf27168e57769c1d86 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 18 Nov 2021 21:26:18 -0600 Subject: [PATCH 17/23] fix: fix building on macos by finding uuid --- CMakeLists.txt | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d569fa82..f5ae435b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,8 +128,43 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # uuid/uuid.h is required by opennurbs - find_package(uuid REQUIRED) - target_include_directories(opennurbs PRIVATE ${uuid_INCLUDE_DIRS}) + message(STATUS "Finding uuid library") + find_package(UUID QUIET) + if(${UUID_FOUND}) + target_include_directories(opennurbs PRIVATE ${UUID_INCLUDE_DIRS}) + else() + # find uuid manually + if(NOT UUID_INCLUDE_DIR) + find_path(UUID_INCLUDE_DIR uuid/uuid.h) + endif() + if(EXISTS "${UUID_INCLUDE_DIR}") + include(CheckCXXSymbolExists) + + set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR}) + set(CMAKE_REQUIRED_INCLUDES ${UUID_INCLUDE_DIRS}) + check_cxx_symbol_exists("uuid_generate_random" "uuid/uuid.h" + _uuid_header_only) + if(NOT _uuid_header_only AND NOT UUID_LIBRARY) + include(CheckLibraryExists) + check_library_exists("uuid" "uuid_generate_random" "" _have_libuuid) + if(_have_libuuid) + set(UUID_LIBRARY "uuid") + endif() + endif() + endif() + + if(UUID_LIBRARY) + set(UUID_LIBRARIES ${UUID_LIBRARY}) + endif() + + unset(CMAKE_REQUIRED_INCLUDES) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(uuid DEFAULT_MSG UUID_INCLUDE_DIR) + + # finally include it + target_include_directories(opennurbs PRIVATE ${UUID_INCLUDE_DIRS}) + endif() endif() # OpenGL From cd6d4c736193857bc9636d27139fc30750dc7235 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 00:35:29 -0600 Subject: [PATCH 18/23] fix: fix building on C++20 - fix removal of shared_ptr.unique This replaces the removed shared_ptr.unique with .use_count() == 1 See this for the explanation https:// en.cppreference.com/w/cpp/memory/shared_ptr/unique --- opennurbs_mesh.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opennurbs_mesh.cpp b/opennurbs_mesh.cpp index c7c78cb2..ca06b819 100644 --- a/opennurbs_mesh.cpp +++ b/opennurbs_mesh.cpp @@ -14831,7 +14831,9 @@ bool ON_MeshCache::Transform( ON_Mesh* mesh = item->m_mesh_sp.get(); if (nullptr == mesh || mesh->IsEmpty()) continue; - if (false == item->m_mesh_sp.unique()) + // NOTE: use_count() == 1 is an approximation in multi-threaded environments + // https:// en.cppreference.com/w/cpp/memory/shared_ptr/unique + if (false == item->m_mesh_sp.use_count() == 1) { // make a copy and transform the copy std::shared_ptr(new ON_Mesh(*mesh)).swap(item->m_mesh_sp); From d8437bfb408e6813fc2959c6efd79634146443a4 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 00:35:51 -0600 Subject: [PATCH 19/23] fix: add the C++ standard if not already specified --- CMakeLists.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5ae435b..47a75c91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,24 @@ cmake_minimum_required(VERSION 3.15) project(opennurbs CXX C) +if(NOT "${CMAKE_CXX_STANDARD}") + # setting the C++ standard if not specified + if(DEFINED CMAKE_CXX20_STANDARD_COMPILE_OPTION + OR DEFINED CMAKE_CXX20_EXTENSION_COMPILE_OPTION) + set(CXX_LATEST_STANDARD 20) + elseif(DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION + OR DEFINED CMAKE_CXX17_EXTENSION_COMPILE_OPTION) + set(CXX_LATEST_STANDARD 17) + elseif(DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION + OR DEFINED CMAKE_CXX14_EXTENSION_COMPILE_OPTION) + set(CXX_LATEST_STANDARD 14) + else() + set(CXX_LATEST_STANDARD 11) + endif() + set(CMAKE_CXX_STANDARD ${CXX_LATEST_STANDARD}) +endif() +message(STATUS "CMAKE_CXX_STANDARD: ${CXX_LATEST_STANDARD}") + # opennurbs source file(GLOB opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/*.h" "${CMAKE_SOURCE_DIR}/*.cpp") From 2d873d31f7773f5a487e8d8f4182b70f1730fed9 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 14:11:42 -0600 Subject: [PATCH 20/23] fix: download dirent for windows on demand --- CMakeLists.txt | 11 +- cross_dirent/.gitignore | 24 - cross_dirent/ChangeLog | 129 ----- cross_dirent/LICENSE | 21 - cross_dirent/README.md | 135 ----- cross_dirent/cross_dirent.h | 11 - cross_dirent/include/dirent.h | 1027 --------------------------------- 7 files changed, 9 insertions(+), 1349 deletions(-) delete mode 100644 cross_dirent/.gitignore delete mode 100644 cross_dirent/ChangeLog delete mode 100644 cross_dirent/LICENSE delete mode 100644 cross_dirent/README.md delete mode 100644 cross_dirent/cross_dirent.h delete mode 100644 cross_dirent/include/dirent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 47a75c91..522b0cb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,8 +137,15 @@ endif() # cross_dirent if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_include_directories( - opennurbs PRIVATE "${CMAKE_SOURCE_DIR}/cross_dirent/include/") + find_path(DIRENT_INCLUDE_DIR dirent.h) + if(${DIRENT_INCLUDE_DIR_FOUND}) + target_include_directories(opennurbs PRIVATE ${DIRENT_INCLUDE_DIR_FOUND}) + else() + file(DOWNLOAD https://github.com/tronkko/dirent/raw/1.23.2/include/dirent.h + ${CMAKE_CURRENT_BINARY_DIR}/_deps/dirent/include/dirent.h) + target_include_directories( + opennurbs PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/_deps/dirent/include/") + endif() endif() # uuid with clang on non-linux, android, windows diff --git a/cross_dirent/.gitignore b/cross_dirent/.gitignore deleted file mode 100644 index 1e9efe31..00000000 --- a/cross_dirent/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -/CMakeCache.txt -/CMakeFiles -/CTestTestfile.cmake -/DartConfiguration.tcl -/Makefile -/Testing -/Win32 -/cmake_install.cmake -/find -/locate -/ls -/scandir -/cat -/t-compile -/t-dirent -/t-scandir -/t-cplusplus -/t-unicode -/t-strverscmp -/t-utf8 -/updatedb -/*.filters -/*.vcxproj -/*.dir diff --git a/cross_dirent/ChangeLog b/cross_dirent/ChangeLog deleted file mode 100644 index d79cea25..00000000 --- a/cross_dirent/ChangeLog +++ /dev/null @@ -1,129 +0,0 @@ -2018-05-08 Toni Rönkkö - - * Version 1.23.2: fixes bad scandir prototype. - -2017-08-27 Toni Rönkkö - - * Version 1.23: support readdir_r and scandir functions. - -2017-07-18 Toni Rönkkö - - * Created release branches v1.22 and v1.21 to Git. Published version - 1.22 at softagalleria.net. - -2016-09-11 Toni Rönkkö - - * Version 1.22: added support for CMake. Thanks to Paul Fultz II. - -2014-09-25 Toni Rönkkö - - * Version 1.21: compiles correctly under Open Watcom. Thanks to - Virgil Banowetz for a patch! - -2014-04-07 Toni Rönkkö - - * Version 1.20.1: the zip file from the previous version did not open - correctly with Microsoft's compressed folders. Thanks to Alexandre - for info! - -2014-03-17 Toni Ronkko - - * Version 1.20: dirent.h compiles correctly in 64-bit architecture. - Thanks to Aaron Simmons! - -2014-03-03 Toni Ronkko - - * Version 1.13.2: define DT_LNK for compatibility with Unix - programs. Thanks to Joel Bruick for suggestion! - -2013-01-27 Toni Ronkko - - * Version 1.13.1: patch from Edward Berner fixes set_errno() on - Windows NT 4.0. - - * Revised wcstombs() and mbstowcs() wrappers to make sure that they do - not write past their target string. - - * PATH_MAX from windows.h includes zero terminator so there is no - need to add one extra byte to variables and structures. - -2012-12-12 Toni Ronkko - - * Version 1.13: use the traditional 8+3 file naming scheme if a file - name cannot be represented in the default ANSI code page. Now - compiles again with MSVC 6.0. Thanks to Konstantin Khomoutov for - testing. - -2012-10-01 Toni Ronkko - - * Version 1.12.1: renamed wide-character DIR structure _wDIR to - _WDIR (with capital W) in order to maintain compatibility with MingW. - -2012-09-30 Toni Ronkko - - * Version 1.12: define PATH_MAX and NAME_MAX. Added wide-character - variants _wDIR, _wdirent, _wopendir(), _wreaddir(), _wclosedir() and - _wrewinddir(). Thanks to Edgar Buerkle and Jan Nijtmans for ideas - and code. - - * Now avoiding windows.h. This allows dirent.h to be integrated - more easily into programs using winsock. Thanks to Fernando - Azaldegui. - -2011-03-15 Toni Ronkko - - * Version 1.11: defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. - -2010-08-11 Toni Ronkko - - * Version 1.10: added d_type and d_namlen fields to dirent structure. - The former is especially useful for determining whether directory - entry represents a file or a directory. For more information, see - http://www.delorie.com/gnu/docs/glibc/libc_270.html - - * Improved conformance to the standards. For example, errno is now - set properly on failure and assert() is never used. Thanks to Peter - Brockam for suggestions. - - * Fixed a bug in rewinddir(): when using relative directory names, - change of working directory no longer causes rewinddir() to fail. - -2009-12-15 John Cunningham - - * Version 1.9: added rewinddir member function - -2008-01-18 Toni Ronkko - - * Version 1.8: Using FindFirstFileA and WIN32_FIND_DATAA to avoid - converting string between multi-byte and unicode representations. - This makes the code simpler and also allows the code to be compiled - under MingW. Thanks to Azriel Fasten for the suggestion. - -2007-03-04 Toni Ronkko - - * Bug fix: due to the strncpy_s() function this file only compiled in - Visual Studio 2005. Using the new string functions only when the - compiler version allows. - -2006-11-02 Toni Ronkko - - * Major update: removed support for Watcom C, MS-DOS and Turbo C to - simplify the file, updated the code to compile cleanly on Visual - Studio 2005 with both unicode and multi-byte character strings, - removed rewinddir() as it had a bug. - -2006-08-20 Toni Ronkko - - * Removed all remarks about MSVC 1.0, which is antiqued now. - Simplified comments by removing SGML tags. - -2002-05-14 Toni Ronkko - - * Embedded the function definitions directly to the header so that no - source modules need to be included in the Visual Studio project. - Removed all the dependencies to other projects so that this header - file can be used independently. - -1998-05-28 Toni Ronkko - - * First version. diff --git a/cross_dirent/LICENSE b/cross_dirent/LICENSE deleted file mode 100644 index af043606..00000000 --- a/cross_dirent/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 1998-2019 Toni Ronkko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/cross_dirent/README.md b/cross_dirent/README.md deleted file mode 100644 index bd31abca..00000000 --- a/cross_dirent/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# Dirent - -Dirent is a C/C++ programming interface that allows programmers to retrieve -information about files and directories under Linux/UNIX. This project -provides Linux compatible Dirent interface for Microsoft Windows. - - -# How to Enable UTF-8 Support - -By default, Dirent functions expect the directory names to be represented in -the currently selected windows codepage. Moverover, Dirent functions return -file names in the presently selected codepage. If you wish to use UTF-8 file -names instead, then set the program's locale to ".utf8" or similar. For -example, your C main program might look like- - -``` -#include - -int main(int argc, char *argv[]) -{ - setlocale(LC_ALL, "LC_CTYPE=.utf8"); - - /*...*/ -} -``` - -For more information on UTF-8 support, please see setlocale in Visual Studio -[C runtime library reference](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-160#utf-8-support). - - -# Installation - -Download the latest Dirent installation package from -[GitHub](https://github.com/tronkko/dirent/releases) and -unpack the installation file with 7-zip, for example. The installation -package contains ``include/dirent.h`` file as well as a few example and test -programs. - - -## Installing Dirent for All Programs - -To make dirent.h available for all C/C++ programs, simply copy the -``include/dirent.h`` file to the system include directory. System include -directory contains header files such as ``assert.h`` and ``windows.h``. In -Visual Studio 2008, for example, the system include may be found at -``C:\Program Files\Microsoft Visual Studio 9.0\VC\include``. - -Everything you need is included in the single ``dirent.h`` file, and you can -start using Dirent immediately -- there is no need to add files to your -Visual Studio project. - - -## Embedding Dirent into Your Own Project - -If you wish to distribute ``dirent.h`` alongside with your own source code, -then copy ``include/dirent.h`` file to a new sub-directory within your project -and add that directory to include path on Windows while omitting the directory -under Linux/UNIX. This allows your project to be compiled against native -``dirent.h`` on Linux/UNIX while substituting the functionality on Microsoft -Windows. - - -## Examples - -The installation package contains six example programs: - -Program | Purpose --------- | ----------------------------------------------------------------- -ls | List files in a directory, e.g. ls "c:\Program Files" -find | Find files in subdirectories, e.g. find "c:\Program Files\CMake" -updatedb | Build database of files in a drive, e.g. updatedb c:\ -locate | Locate a file from database, e.g. locate notepad -scandir | Demonstrate scandir() function -cat | Print a text file to screen - -Please install [CMake](https://cmake.org/) to build example and test programs. -Then, open command prompt and create a temporary directory ``c:\temp\dirent`` -for the build files as - -``` -c:\ -mkdir temp -mkdir temp\dirent -cd temp\dirent -``` - -Generate build files as - -``` -cmake d:\dirent -``` - -where ``d:\dirent`` is the root directory of the Dirent package (containing -this README.md file). If wish to omit example programs from the -build, then append the option ``-DDIRENT_BUILD_TESTS=OFF`` to the CMake -command line. - -Once CMake is finished, open Visual Studio, load the generated ``dirent.sln`` -file from the build directory and build the whole solution. Once the build -completes, run the example programs ls, find, updatedb and locate from the -command prompt as - -``` -cd Debug -ls . -find . -updatedb c:\ -locate cmd.exe -``` - -Visual Studio project also contains a solution named ``check`` which can be -used to verify that Dirent works as expected. Just build the solution from -Visual Studio to run the test programs. - - -# Contributing - -We love to receive contributions from you. See the -[CONTRIBUTING](CONTRIBUTING.md) file for details. - - -# Copying - -Dirent may be freely distributed under the MIT license. See the -[LICENSE](LICENSE) file for details. - - -# Alternatives to Dirent - -I ported Dirent to Microsoft Windows in 1998 when only a few alternatives -were available. However, the situation has changed since then and nowadays -both [Cygwin](http://www.cygwin.com) and [MingW](http://www.mingw.org) -allow you to compile a great number of UNIX programs in Microsoft Windows. -They both provide a full dirent API as well as many other UNIX APIs. MingW -can even be used for commercial applications! diff --git a/cross_dirent/cross_dirent.h b/cross_dirent/cross_dirent.h deleted file mode 100644 index bc45af96..00000000 --- a/cross_dirent/cross_dirent.h +++ /dev/null @@ -1,11 +0,0 @@ -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - -// if not windows use the posix dirent.h -#include - -#else - -// use dirent windows -#include "./include/dirent.h" - -#endif \ No newline at end of file diff --git a/cross_dirent/include/dirent.h b/cross_dirent/include/dirent.h deleted file mode 100644 index a2e847a0..00000000 --- a/cross_dirent/include/dirent.h +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Dirent interface for Microsoft Visual Studio - * - * Copyright (C) 1998-2019 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - */ -#ifndef DIRENT_H -#define DIRENT_H - -/* Hide warnings about unreferenced local functions */ -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#elif defined(_MSC_VER) -# pragma warning(disable:4505) -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif - -/* - * Include windows.h without Windows Sockets 1.1 to prevent conflicts with - * Windows Sockets 2.0. - */ -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Indicates that d_type field is available in dirent structure */ -#define _DIRENT_HAVE_D_TYPE - -/* Indicates that d_namlen field is available in dirent structure */ -#define _DIRENT_HAVE_D_NAMLEN - -/* Entries missing from MSVC 6.0 */ -#if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 -#endif - -/* File type and permission flags for stat(), general mask */ -#if !defined(S_IFMT) -# define S_IFMT _S_IFMT -#endif - -/* Directory bit */ -#if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR -#endif - -/* Character device bit */ -#if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR -#endif - -/* Pipe bit */ -#if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO -#endif - -/* Regular file bit */ -#if !defined(S_IFREG) -# define S_IFREG _S_IFREG -#endif - -/* Read permission */ -#if !defined(S_IREAD) -# define S_IREAD _S_IREAD -#endif - -/* Write permission */ -#if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE -#endif - -/* Execute permission */ -#if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC -#endif - -/* Pipe */ -#if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO -#endif - -/* Block device */ -#if !defined(S_IFBLK) -# define S_IFBLK 0 -#endif - -/* Link */ -#if !defined(S_IFLNK) -# define S_IFLNK 0 -#endif - -/* Socket */ -#if !defined(S_IFSOCK) -# define S_IFSOCK 0 -#endif - -/* Read user permission */ -#if !defined(S_IRUSR) -# define S_IRUSR S_IREAD -#endif - -/* Write user permission */ -#if !defined(S_IWUSR) -# define S_IWUSR S_IWRITE -#endif - -/* Execute user permission */ -#if !defined(S_IXUSR) -# define S_IXUSR 0 -#endif - -/* Read group permission */ -#if !defined(S_IRGRP) -# define S_IRGRP 0 -#endif - -/* Write group permission */ -#if !defined(S_IWGRP) -# define S_IWGRP 0 -#endif - -/* Execute group permission */ -#if !defined(S_IXGRP) -# define S_IXGRP 0 -#endif - -/* Read others permission */ -#if !defined(S_IROTH) -# define S_IROTH 0 -#endif - -/* Write others permission */ -#if !defined(S_IWOTH) -# define S_IWOTH 0 -#endif - -/* Execute others permission */ -#if !defined(S_IXOTH) -# define S_IXOTH 0 -#endif - -/* Maximum length of file name */ -#if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH -#endif -#if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH -#endif -#if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX -#endif - -/* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK -#define DT_LNK S_IFLNK - -/* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) -#define DTTOIF(type) (type) - -/* - * File type macros. Note that block devices, sockets and links cannot be - * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are - * only defined for compatibility. These macros should always return false - * on Windows. - */ -#if !defined(S_ISFIFO) -# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) -# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISLNK) -# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISSOCK) -# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISCHR) -# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#endif -#if !defined(S_ISBLK) -# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) -#endif - -/* Return the exact length of the file name without zero terminator */ -#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) - -/* Return the maximum size of a file name */ -#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Wide-character version */ -struct _wdirent { - /* Always zero */ - long d_ino; - - /* File position within stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - wchar_t d_name[PATH_MAX+1]; -}; -typedef struct _wdirent _wdirent; - -struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; - - /* Private file data */ - WIN32_FIND_DATAW data; - - /* True if data is valid */ - int cached; - - /* Win32 search handle */ - HANDLE handle; - - /* Initial directory name */ - wchar_t *patt; -}; -typedef struct _WDIR _WDIR; - -/* Multi-byte character version */ -struct dirent { - /* Always zero */ - long d_ino; - - /* File position within stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - char d_name[PATH_MAX+1]; -}; -typedef struct dirent dirent; - -struct DIR { - struct dirent ent; - struct _WDIR *wdirp; -}; -typedef struct DIR DIR; - - -/* Dirent functions */ -static DIR *opendir(const char *dirname); -static _WDIR *_wopendir(const wchar_t *dirname); - -static struct dirent *readdir(DIR *dirp); -static struct _wdirent *_wreaddir(_WDIR *dirp); - -static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result); -static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); - -static int closedir(DIR *dirp); -static int _wclosedir(_WDIR *dirp); - -static void rewinddir(DIR* dirp); -static void _wrewinddir(_WDIR* dirp); - -static int scandir(const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)); - -static int alphasort(const struct dirent **a, const struct dirent **b); - -static int versionsort(const struct dirent **a, const struct dirent **b); - -static int strverscmp(const char *a, const char *b); - -/* For compatibility with Symbian */ -#define wdirent _wdirent -#define WDIR _WDIR -#define wopendir _wopendir -#define wreaddir _wreaddir -#define wclosedir _wclosedir -#define wrewinddir _wrewinddir - -/* Compatibility with older Microsoft compilers and non-Microsoft compilers */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -# define wcstombs_s dirent_wcstombs_s -# define mbstowcs_s dirent_mbstowcs_s -#endif - -/* Optimize dirent_set_errno() away on modern Microsoft compilers */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 -# define dirent_set_errno _set_errno -#endif - - -/* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, - const char *mbstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, size_t sizeInBytes, - const wchar_t *wcstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void dirent_set_errno(int error); -#endif - - -/* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static _WDIR *_wopendir(const wchar_t *dirname) -{ - wchar_t *p; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate new _WDIR structure */ - _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR)); - if (!dirp) - return NULL; - - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; - - /* - * Compute the length of full path plus zero terminator - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL); -#else - /* WinRT */ - size_t n = wcslen(dirname); -#endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16); - if (dirp->patt == NULL) - goto exit_closedir; - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - n = GetFullPathNameW(dirname, n, dirp->patt, NULL); - if (n <= 0) - goto exit_closedir; -#else - /* WinRT */ - wcsncpy_s(dirp->patt, n+1, dirname, n); -#endif - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - *p++ = '*'; - *p = '\0'; - - /* Open directory stream and retrieve the first entry */ - if (!dirent_first(dirp)) - goto exit_closedir; - - /* Success */ - return dirp; - - /* Failure */ -exit_closedir: - _wclosedir(dirp); - return NULL; -} - -/* - * Read next directory entry. - * - * Returns pointer to static directory entry which may be overwritten by - * subsequent calls to _wreaddir(). - */ -static struct _wdirent *_wreaddir(_WDIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct _wdirent *entry; - (void) _wreaddir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry. - * - * Returns zero on success. If end of directory stream is reached, then sets - * result to NULL and returns zero. - */ -static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result) -{ - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* Return NULL to indicate end of directory */ - *result = NULL; - return /*OK*/0; - } - - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - size_t n = 0; - while (n < PATH_MAX && datap->cFileName[n] != 0) { - entry->d_name[n] = datap->cFileName[n]; - n++; - } - entry->d_name[n] = 0; - - /* Length of file name excluding zero terminator */ - entry->d_namlen = n; - - /* File type */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof(struct _wdirent); - - /* Set result address */ - *result = entry; - return /*OK*/0; -} - -/* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ -static int _wclosedir(_WDIR *dirp) -{ - if (!dirp) { - dirent_set_errno(EBADF); - return /*failure*/-1; - } - - /* Release search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) - FindClose(dirp->handle); - - /* Release search pattern */ - free(dirp->patt); - - /* Release directory structure */ - free(dirp); - return /*success*/0; -} - -/* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ -static void _wrewinddir(_WDIR* dirp) -{ - if (!dirp) - return; - - /* Release existing search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) - FindClose(dirp->handle); - - /* Open new search handle */ - dirent_first(dirp); -} - -/* Get first directory entry */ -static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp) -{ - if (!dirp) - return NULL; - - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle == INVALID_HANDLE_VALUE) - goto error; - - /* A directory entry is now waiting in memory */ - dirp->cached = 1; - return &dirp->data; - -error: - /* Failed to open directory: no directory entry in memory */ - dirp->cached = 0; - - /* Set error code */ - DWORD errorcode = GetLastError(); - switch (errorcode) { - case ERROR_ACCESS_DENIED: - /* No read access to directory */ - dirent_set_errno(EACCES); - break; - - case ERROR_DIRECTORY: - /* Directory name is invalid */ - dirent_set_errno(ENOTDIR); - break; - - case ERROR_PATH_NOT_FOUND: - default: - /* Cannot find the file */ - dirent_set_errno(ENOENT); - } - return NULL; -} - -/* Get next directory entry */ -static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp) -{ - /* Is the next directory entry already in cache? */ - if (dirp->cached) { - /* Yes, a valid directory entry found in memory */ - dirp->cached = 0; - return &dirp->data; - } - - /* No directory entry in cache */ - if (dirp->handle == INVALID_HANDLE_VALUE) - return NULL; - - /* Read the next directory entry from stream */ - if (FindNextFileW(dirp->handle, &dirp->data) == FALSE) - goto exit_close; - - /* Success */ - return &dirp->data; - - /* Failure */ -exit_close: - FindClose(dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - return NULL; -} - -/* Open directory stream using plain old C-string */ -static DIR *opendir(const char *dirname) -{ - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate memory for DIR structure */ - struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR)); - if (!dirp) - return NULL; - - /* Convert directory name to wide-character string */ - wchar_t wname[PATH_MAX + 1]; - size_t n; - int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1); - if (error) - goto exit_failure; - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir(wname); - if (!dirp->wdirp) - goto exit_failure; - - /* Success */ - return dirp; - - /* Failure */ -exit_failure: - free(dirp); - return NULL; -} - -/* Read next directory entry */ -static struct dirent *readdir(DIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct dirent *entry; - (void) readdir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry into called-allocated buffer. - * - * Returns zero on success. If the end of directory stream is reached, then - * sets result to NULL and returns zero. - */ -static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result) -{ - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp); - if (!datap) { - /* No more directory entries */ - *result = NULL; - return /*OK*/0; - } - - /* Attempt to convert file name to multi-byte string */ - size_t n; - int error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cFileName, PATH_MAX + 1); - - /* - * If the file name cannot be represented by a multi-byte string, then - * attempt to use old 8+3 file name. This allows the program to - * access files although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file name - * unless the file system provides one. At least VirtualBox shared - * folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cAlternateFileName, PATH_MAX + 1); - } - - if (!error) { - /* Length of file name excluding zero terminator */ - entry->d_namlen = n - 1; - - /* File attributes */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Reset dummy fields */ - entry->d_ino = 0; - entry->d_off = 0; - entry->d_reclen = sizeof(struct dirent); - } else { - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entry->d_name[0] = '?'; - entry->d_name[1] = '\0'; - entry->d_namlen = 1; - entry->d_type = DT_UNKNOWN; - entry->d_ino = 0; - entry->d_off = -1; - entry->d_reclen = 0; - } - - /* Return pointer to directory entry */ - *result = entry; - return /*OK*/0; -} - -/* Close directory stream */ -static int closedir(DIR *dirp) -{ - int ok; - - if (!dirp) - goto exit_failure; - - /* Close wide-character directory stream */ - ok = _wclosedir(dirp->wdirp); - dirp->wdirp = NULL; - - /* Release multi-byte character version */ - free(dirp); - return ok; - -exit_failure: - /* Invalid directory stream */ - dirent_set_errno(EBADF); - return /*failure*/-1; -} - -/* Rewind directory stream to beginning */ -static void rewinddir(DIR* dirp) -{ - if (!dirp) - return; - - /* Rewind wide-character string directory stream */ - _wrewinddir(dirp->wdirp); -} - -/* Scan directory for entries */ -static int scandir( - const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)) -{ - int result; - - /* Open directory stream */ - DIR *dir = opendir(dirname); - if (!dir) { - /* Cannot open directory */ - return /*Error*/ -1; - } - - /* Read directory entries to memory */ - struct dirent *tmp = NULL; - struct dirent **files = NULL; - size_t size = 0; - size_t allocated = 0; - while (1) { - /* Allocate room for a temporary directory entry */ - if (!tmp) { - tmp = (struct dirent*) malloc(sizeof(struct dirent)); - if (!tmp) - goto exit_failure; - } - - /* Read directory entry to temporary area */ - struct dirent *entry; - if (readdir_r(dir, tmp, &entry) != /*OK*/0) - goto exit_failure; - - /* Stop if we already read the last directory entry */ - if (entry == NULL) - goto exit_success; - - /* Determine whether to include the entry in results */ - if (filter && !filter(tmp)) - continue; - - /* Enlarge pointer table to make room for another pointer */ - if (size >= allocated) { - /* Compute number of entries in the new table */ - size_t num_entries = size * 2 + 16; - - /* Allocate new pointer table or enlarge existing */ - void *p = realloc(files, sizeof(void*) * num_entries); - if (!p) - goto exit_failure; - - /* Got the memory */ - files = (dirent**) p; - allocated = num_entries; - } - - /* Store the temporary entry to ptr table */ - files[size++] = tmp; - tmp = NULL; - } - -exit_failure: - /* Release allocated file entries */ - for (size_t i = 0; i < size; i++) { - free(files[i]); - } - - /* Release the pointer table */ - free(files); - files = NULL; - - /* Exit with error code */ - result = /*error*/ -1; - goto exit_status; - -exit_success: - /* Sort directory entries */ - qsort(files, size, sizeof(void*), - (int (*) (const void*, const void*)) compare); - - /* Pass pointer table to caller */ - if (namelist) - *namelist = files; - - /* Return the number of directory entries read */ - result = (int) size; - -exit_status: - /* Release temporary directory entry, if we had one */ - free(tmp); - - /* Close directory stream */ - closedir(dir); - return result; -} - -/* Alphabetical sorting */ -static int alphasort(const struct dirent **a, const struct dirent **b) -{ - return strcoll((*a)->d_name, (*b)->d_name); -} - -/* Sort versions */ -static int versionsort(const struct dirent **a, const struct dirent **b) -{ - return strverscmp((*a)->d_name, (*b)->d_name); -} - -/* Compare strings */ -static int strverscmp(const char *a, const char *b) -{ - size_t i = 0; - size_t j; - - /* Find first difference */ - while (a[i] == b[i]) { - if (a[i] == '\0') { - /* No difference */ - return 0; - } - ++i; - } - - /* Count backwards and find the leftmost digit */ - j = i; - while (j > 0 && isdigit(a[j-1])) { - --j; - } - - /* Determine mode of comparison */ - if (a[j] == '0' || b[j] == '0') { - /* Find the next non-zero digit */ - while (a[j] == '0' && a[j] == b[j]) { - j++; - } - - /* String with more digits is smaller, e.g 002 < 01 */ - if (isdigit(a[j])) { - if (!isdigit(b[j])) { - return -1; - } - } else if (isdigit(b[j])) { - return 1; - } - } else if (isdigit(a[j]) && isdigit(b[j])) { - /* Numeric comparison */ - size_t k1 = j; - size_t k2 = j; - - /* Compute number of digits in each string */ - while (isdigit(a[k1])) { - k1++; - } - while (isdigit(b[k2])) { - k2++; - } - - /* Number with more digits is bigger, e.g 999 < 1000 */ - if (k1 < k2) - return -1; - else if (k1 > k2) - return 1; - } - - /* Alphabetical comparison */ - return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]); -} - -/* Convert multi-byte string to wide character string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, - size_t sizeInWords, const char *mbstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = mbstowcs(wcstr, mbstr, sizeInWords); - if (wcstr && n >= count) - return /*error*/ 1; - - /* Zero-terminate output buffer */ - if (wcstr && sizeInWords) { - if (n >= sizeInWords) - n = sizeInWords - 1; - wcstr[n] = 0; - } - - /* Length of multi-byte string with zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Convert wide-character string to multi-byte string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, - size_t sizeInBytes, const wchar_t *wcstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = wcstombs(mbstr, wcstr, sizeInBytes); - if (mbstr && n >= count) - return /*error*/1; - - /* Zero-terminate output buffer */ - if (mbstr && sizeInBytes) { - if (n >= sizeInBytes) { - n = sizeInBytes - 1; - } - mbstr[n] = '\0'; - } - - /* Length of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Set errno variable */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void dirent_set_errno(int error) -{ - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; -} -#endif - -#ifdef __cplusplus -} -#endif -#endif /*DIRENT_H*/ From a7e95fc53a30db747d546cbf5a0ebc2f5f93dabe Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 15:11:44 -0600 Subject: [PATCH 21/23] fix: only include android_uuid on linux and android --- CMakeLists.txt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 522b0cb3..91de0c6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ message(STATUS "CMAKE_CXX_STANDARD: ${CXX_LATEST_STANDARD}") # opennurbs source file(GLOB opennurbs_SOURCE "${CMAKE_SOURCE_DIR}/*.h" "${CMAKE_SOURCE_DIR}/*.cpp") +# exclude the examples +list(FILTER opennurbs_SOURCE EXCLUDE REGEX "${CMAKE_SOURCE_DIR}/example*") if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") list(REMOVE_ITEM opennurbs_SOURCE @@ -61,10 +63,14 @@ else() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") add_library(opennurbs STATIC ${opennurbs_SOURCE}) else() - # Include UUID source (bundled with opennurbs) - file(GLOB UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/*.h" - "${CMAKE_SOURCE_DIR}/android_uuid/*.c") - list(REMOVE_ITEM UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/gen_uuid_nt.c") + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL + "Android") + # Include UUID source (bundled with opennurbs) + file(GLOB UUID_SRC "${CMAKE_SOURCE_DIR}/android_uuid/*.h" + "${CMAKE_SOURCE_DIR}/android_uuid/*.c") + list(REMOVE_ITEM UUID_SRC + "${CMAKE_SOURCE_DIR}/android_uuid/gen_uuid_nt.c") + endif() # Need to combine all source files for static linking on non-windows add_library(opennurbs STATIC ${UUID_SRC} ${opennurbs_SOURCE}) From dc9ccbb85b7f754aa20a322cfcb76c189efc3510 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 15:42:42 -0600 Subject: [PATCH 22/23] docs: add -DCMAKE_FIND_FRAMEWORK=LAST for macos --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 69f5dafd..a8fe317c 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,12 @@ There's also a collection of [example 3dm files](example_files/) available for t 2. `cd` to the root directory of the repository. 3. Run the following to configure the CMake files. ``` -cmake -S ./ -B ./build +cmake -S ./ -B ./build -DCMAKE_FIND_FRAMEWORK=LAST ``` Note: if [ninja-build](https://ninja-build.org/) is installed, you can specify `Ninja` to speed up the build: ``` - cmake -S ./ -B ./build -G "Ninja Multi-Config" + cmake -S ./ -B ./build -G "Ninja Multi-Config" -DCMAKE_FIND_FRAMEWORK=LAST ``` Note: To use Ninja with the Visual Studio Compiler, open the MSVC command prompt (or run `vcvarsall.bat`), and run: @@ -47,6 +47,8 @@ cmake -S ./ -B ./build cmake -S ./ -B ./build -G "Ninja Multi-Config" -D CMAKE_CXX_COMPILER=cl -D CMAKE_C_COMPILER=cl ``` + Note: `-DCMAKE_FIND_FRAMEWORK=LAST` fixes the issue of the MacOS compilers that choose an incorrect framework to build system headers. + 4. Finally, run the following to build the library. ``` cmake --build ./build --config Release From fe1747a5f7eaee2dd6a6404dc24a10ec3482da8a Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Fri, 19 Nov 2021 18:02:33 -0600 Subject: [PATCH 23/23] fix: fix build for windows arm64 --- CMakeLists.txt | 1 + README.md | 2 ++ opennurbs_file_utilities.cpp | 6 +++--- opennurbs_precompiledheader.cpp | 20 ++++++++++---------- opennurbs_system.h | 4 ++-- opennurbs_system_runtime.h | 4 ++-- opennurbs_version_number.cpp | 2 +- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91de0c6f..e4ccf834 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") # Fix "WIN32" preprocessor definitions on x64 if(${CMAKE_SIZEOF_VOID_P} EQUAL "8") + message(STATUS "Removing WIN32 definition for 64 bit build of opennurbs") string(REPLACE "/DWIN32" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") target_compile_definitions(opennurbs PRIVATE WIN64) endif() diff --git a/README.md b/README.md index a8fe317c..93e722cf 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ cmake -S ./ -B ./build -DCMAKE_FIND_FRAMEWORK=LAST Note: `-DCMAKE_FIND_FRAMEWORK=LAST` fixes the issue of the MacOS compilers that choose an incorrect framework to build system headers. + Note: Additionally, pass `-A ARM64` to build for ARM64. + 4. Finally, run the following to build the library. ``` cmake --build ./build --config Release diff --git a/opennurbs_file_utilities.cpp b/opennurbs_file_utilities.cpp index 20e7e85d..e6e98719 100644 --- a/opennurbs_file_utilities.cpp +++ b/opennurbs_file_utilities.cpp @@ -37,7 +37,7 @@ #pragma ON_PRAGMA_WARNING_BEFORE_DIRTY_INCLUDE #include #pragma ON_PRAGMA_WARNING_AFTER_DIRTY_INCLUDE -#if defined(_M_X64) && defined(WIN32) && defined(WIN64) +#if (defined(_M_X64) || defined(_M_ARM64)) && defined(WIN32) && defined(WIN64) // Shlwapi.h, Shlobj.h and perhaps others, unconditionally define WIN32 #undef WIN32 #endif @@ -3302,13 +3302,13 @@ void ON_ContentHash::Dump( const ON_wString content_time = ( m_content_time <= 0 ) - ? L"unknown" + ? static_cast(L"unknown") : SecondsSinceJanOne1970UTCToString(m_content_time); text_log.Print(L"Content last modified time = %ls\n",static_cast(content_time)); const ON_wString hash_time = ( m_hash_time <= 0 ) - ? L"unknown" + ? static_cast(L"unknown") : SecondsSinceJanOne1970UTCToString(m_hash_time); text_log.Print(L"Content hash calculated time = %ls\n",static_cast(content_time)); diff --git a/opennurbs_precompiledheader.cpp b/opennurbs_precompiledheader.cpp index 38b46206..2aa370ec 100644 --- a/opennurbs_precompiledheader.cpp +++ b/opennurbs_precompiledheader.cpp @@ -32,9 +32,9 @@ #error Incorrect _M_... setting for x64 build #endif -#if !defined(_M_X64) +#if !defined(_M_X64) && !defined(_M_ARM64) // This should be automatically defined by the compiler -#error _M_X64 should be defined for x64 builds +#error _M_X64 or _M_ARM64 should be defined for x64 or ARM64 builds #endif // All opennurbs code uses the "offical" _M_X64. Unfortunately, @@ -43,9 +43,9 @@ // _M_X64 and _M_AMD64 for the WIN64 platform. If it doesn't, // then we have a serious problem because some system header // files will not be correctly preprocessed. -#if !defined(_M_AMD64) +#if !defined(_M_AMD64) && !defined(_M_ARM64) // This should be automatically defined by the compiler -#error _M_AMD64 should be defined for x64 builds +#error _M_AMD64 or _M_ARM64 should be defined for x64 or ARM64 builds #endif #endif @@ -57,7 +57,7 @@ #error Microsoft defines _WIN32 for all Windows builds #endif -#if defined(_M_IA64) || defined(_M_X64) || defined(_M_AMD64) +#if defined(_M_IA64) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64) #error Incorrect _M_... setting for 32 bit Windows build. #endif @@ -108,9 +108,9 @@ #error Incorrect _M_... setting for x64 build #endif -#if !defined(_M_X64) +#if !defined(_M_X64) && !defined(_M_ARM64) // This should be automatically defined by the compiler -#error _M_X64 should be defined for x64 builds +#error _M_X64 or _M_ARM64 should be defined for x64 or ARM64 builds #endif // All opennurbs code uses the "offical" _M_X64. Unfortunately, @@ -119,9 +119,9 @@ // _M_X64 and _M_AMD64 for the WIN64 platform. If it doesn't, // then we have a serious problem because some system header // files will not be correctly preprocessed. -#if !defined(_M_AMD64) +#if !defined(_M_AMD64) && !defined(_M_ARM64) // This should be automatically defined by the compiler -#error _M_AMD64 should be defined for x64 builds +#error _M_AMD64 or _M_ARM64 should be defined for x64 or ARM6 builds #endif #endif @@ -133,7 +133,7 @@ #error Microsoft defines _WIN32 for all Windows builds #endif -#if defined(_M_IA64) || defined(_M_X64) || defined(_M_AMD64) +#if defined(_M_IA64) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64) #error Incorrect _M_... setting for 32 bit Windows build. #endif diff --git a/opennurbs_system.h b/opennurbs_system.h index a92eb9a8..4aa458fd 100644 --- a/opennurbs_system.h +++ b/opennurbs_system.h @@ -383,7 +383,7 @@ typedef ON__UINT32 wchar_t; */ -#if defined(_M_X64) && defined(WIN32) && defined(WIN64) +#if (defined(_M_X64) || defined(_M_ARM64)) && defined(WIN32) && defined(WIN64) // 23 August 2007 Dale Lear #if defined(_INC_WINDOWS) @@ -406,7 +406,7 @@ typedef ON__UINT32 wchar_t; #pragma ON_PRAGMA_WARNING_AFTER_DIRTY_INCLUDE #endif -#if defined(_M_X64) && defined(WIN32) && defined(WIN64) +#if (defined(_M_X64) || defined(_M_ARM64)) && defined(WIN32) && defined(WIN64) // 23 August 2007 Dale Lear // windows.h unconditionally defines WIN32 This is a bug // and the hope is this simple undef will let us continue. diff --git a/opennurbs_system_runtime.h b/opennurbs_system_runtime.h index 683b73ef..f2e4ae56 100644 --- a/opennurbs_system_runtime.h +++ b/opennurbs_system_runtime.h @@ -137,7 +137,7 @@ #define ON_RUNTIME_WIN_WINOS #endif -#if defined(_M_X64) || defined(_WIN64) +#if defined(_M_X64) || defined(_M_ARM64) || defined(_WIN64) #define ON_64BIT_RUNTIME #elif defined(_M_X86) || defined(_WIN32) #define ON_32BIT_RUNTIME @@ -146,7 +146,7 @@ #endif #if !defined(ON_LITTLE_ENDIAN) -#if (defined(_M_X64) || defined(_M_IX86) || defined (__i386__) || defined( __x86_64__ )) +#if (defined(_M_X64) || defined(_M_ARM64) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) #define ON_LITTLE_ENDIAN #endif #endif diff --git a/opennurbs_version_number.cpp b/opennurbs_version_number.cpp index 7ca9e81c..65379a76 100644 --- a/opennurbs_version_number.cpp +++ b/opennurbs_version_number.cpp @@ -375,7 +375,7 @@ const ON_String ON_VersionNumberToString( str_version = (0 != version_number) ? ON_String::FormatToString("0x%08X", version_number) - : "0"; + : static_cast("0"); } return str_version;