Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CMake support for OpenNURBS #29

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
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")
# 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
"${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})
# if dynamic

# opennurbs shared library
add_library(opennurbs SHARED ${opennurbs_SOURCE})

# 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

if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_library(opennurbs STATIC ${opennurbs_SOURCE})
else()
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})
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
OPENNURBS_INPUT_LIBS_DIR="${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>"
UNICODE)

if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
# Windows specific

# 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()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Linux specific

# Linux compiler definitions
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

# zlib
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 ${ZLIB_SOURCE})
target_compile_definitions(zlib PRIVATE MY_ZCALLOC Z_PREFIX)
set_target_properties(
zlib PROPERTIES ARCHIVE_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
set(opennurbs_ZLIB_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
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)

# shlwapi on windows
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_link_libraries(opennurbs PRIVATE shlwapi)
endif()

# cross_dirent
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
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
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
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
if(${OPENGL_FOUND})
target_link_libraries(opennurbs PRIVATE OpenGL::GL OpenGL::GLU)
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}")
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,54 @@ 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 the following to configure the CMake files.
```
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" -DCMAKE_FIND_FRAMEWORK=LAST
```

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
```

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
```

### 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?

For technical support, please head over to [Discourse](https://discourse.mcneel.com/category/opennurbs).
8 changes: 4 additions & 4 deletions opennurbs_locale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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 };
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions opennurbs_string_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions opennurbs_string_scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -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))
{
Expand Down
2 changes: 2 additions & 0 deletions opennurbs_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Rpc.h>
#else
#include <uuid/uuid.h>
#endif
Expand Down