diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 006b406ba07..f51d71998fd 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -287,8 +287,12 @@ Note that this requires linking Boost statically" set(BROTLI_MSVC_STATIC_LIB_SUFFIX "-static" CACHE STRING "Brotli static lib suffix used on Windows with MSVC (default -static)") + set(PROTOBUF_MSVC_STATIC_LIB_SUFFIX "" CACHE STRING + "Protobuf static lib suffix used on Windows with MSVC (default is empty string)") + set(RE2_MSVC_STATIC_LIB_SUFFIX "_static" CACHE STRING + "re2 static lib suffix used on Windows with MSVC (default is _static)") set(SNAPPY_MSVC_STATIC_LIB_SUFFIX "_static" CACHE STRING - "Snappy static lib suffix used on Windows with MSVC (default is empty string)") + "Snappy static lib suffix used on Windows with MSVC (default is _static)") set(LZ4_MSVC_STATIC_LIB_SUFFIX "_static" CACHE STRING "Lz4 static lib suffix used on Windows with MSVC (default _static)") set(ZSTD_MSVC_STATIC_LIB_SUFFIX "_static" CACHE STRING diff --git a/cpp/build-support/lint_cpp_cli.py b/cpp/build-support/lint_cpp_cli.py index c8b25dfc5e4..9dbc005da6c 100644 --- a/cpp/build-support/lint_cpp_cli.py +++ b/cpp/build-support/lint_cpp_cli.py @@ -42,6 +42,10 @@ def _strip_comments(line): return m.group(0) +def _path(*tokens): + return os.path.sep.join(tokens) + + def lint_file(path): fail_rules = [ # rule, error message, rule-specific exclusions list @@ -49,10 +53,10 @@ def lint_file(path): (lambda x: re.match(_NULLPTR_REGEX, x), 'Uses nullptr', []), (lambda x: re.match(_RETURN_NOT_OK_REGEX, x), 'Use ARROW_RETURN_NOT_OK in header files', - ['arrow/status.h', + [_path('arrow', 'status.h'), 'test', - 'arrow/util/hash.h', - 'arrow/python/util']) + _path('arrow', 'util', 'hash.h'), + _path('arrow', 'python', 'util')]) ] with open(path) as f: @@ -69,14 +73,14 @@ def lint_file(path): EXCLUSIONS = [ - 'arrow/python/iterators.h', - 'arrow/util/hashing.h', - 'arrow/util/macros.h', - 'arrow/util/parallel.h', - 'arrow/vendored', - 'arrow/visitor_inline.h', - 'gandiva/cache.h', - 'gandiva/jni', + _path('arrow', 'python', 'iterators.h'), + _path('arrow', 'util', 'hashing.h'), + _path('arrow', 'util', 'macros.h'), + _path('arrow', 'util', 'parallel.h'), + _path('arrow', 'vendored'), + _path('arrow', 'visitor_inline.h'), + _path('gandiva', 'cache.h'), + _path('gandiva', 'jni'), 'test', 'internal' ] diff --git a/cpp/cmake_modules/FindProtobuf.cmake b/cpp/cmake_modules/FindProtobuf.cmake index e4a87f4f9ca..f53f48d6068 100644 --- a/cpp/cmake_modules/FindProtobuf.cmake +++ b/cpp/cmake_modules/FindProtobuf.cmake @@ -44,12 +44,12 @@ if (EXISTS "${_protobuf_path}/lib/${CMAKE_LIBRARY_ARCHITECTURE}") set (lib_dirs "lib/${CMAKE_LIBRARY_ARCHITECTURE}" ${lib_dirs}) endif () -find_library (PROTOBUF_LIBRARY NAMES protobuf PATHS +find_library (PROTOBUF_LIBRARY NAMES protobuf libprotobuf PATHS ${_protobuf_path} NO_DEFAULT_PATH PATH_SUFFIXES ${lib_dirs}) -find_library (PROTOC_LIBRARY NAMES protoc PATHS +find_library (PROTOC_LIBRARY NAMES protoc libprotoc PATHS ${_protobuf_path} NO_DEFAULT_PATH PATH_SUFFIXES ${lib_dirs}) @@ -66,7 +66,7 @@ if (PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY AND PROTOC_LIBRARY AND PROTOBUF_EX get_filename_component (PROTOBUF_LIBS ${PROTOBUF_LIBRARY} PATH) set (PROTOBUF_LIB_NAME protobuf) set (PROTOC_LIB_NAME protoc) - set (PROTOBUF_STATIC_LIB ${PROTOBUF_LIBS}/${CMAKE_STATIC_LIBRARY_PREFIX}${PROTOBUF_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}) + set (PROTOBUF_STATIC_LIB ${PROTOBUF_LIBS}/${CMAKE_STATIC_LIBRARY_PREFIX}${PROTOBUF_LIB_NAME}${PROTOBUF_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) set (PROTOC_STATIC_LIB ${PROTOBUF_LIBS}/${CMAKE_STATIC_LIBRARY_PREFIX}${PROTOC_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}) else () set (PROTOBUF_FOUND FALSE) @@ -81,7 +81,7 @@ if (PROTOBUF_FOUND) message (STATUS "Found the Protoc executable: ${PROTOBUF_EXECUTABLE}") else() if (_protobuf_path) - set (PROTOBUF_ERR_MSG "Could not find Protobuf. Looked in ${_protobuf_path}.") + set (PROTOBUF_ERR_MSG "Could not find Protobuf. Looked in ${_protobuf_path}") else () set (PROTOBUF_ERR_MSG "Could not find Protobuf in system search paths.") endif() @@ -100,4 +100,3 @@ mark_as_advanced ( PROTOBUF_STATIC_LIB PROTOC_STATIC_LIB ) - diff --git a/cpp/cmake_modules/FindRE2.cmake b/cpp/cmake_modules/FindRE2.cmake index ae0f182d0e4..51b093fc977 100644 --- a/cpp/cmake_modules/FindRE2.cmake +++ b/cpp/cmake_modules/FindRE2.cmake @@ -45,14 +45,18 @@ if (EXISTS "${_re2_path}/lib/${CMAKE_LIBRARY_ARCHITECTURE}") set (lib_dirs "lib/${CMAKE_LIBRARY_ARCHITECTURE}" ${lib_dirs}) endif () -find_library(RE2_STATIC_LIB NAMES libre2${CMAKE_STATIC_LIBRARY_SUFFIX} +set(RE2_LIB_NAME re2) +set(RE2_STATIC_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}${RE2_LIB_NAME}${RE2_MSVC_STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) +set(RE2_SHARED_LIB_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}${RE2_LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) + +find_library(RE2_STATIC_LIB NAMES ${RE2_STATIC_LIB_NAME} PATHS ${_re2_path} NO_DEFAULT_PATH PATH_SUFFIXES ${lib_dirs} DOC "Google's re2 regex static library" ) -find_library(RE2_SHARED_LIB NAMES libre2${CMAKE_SHARED_LIBRARY_SUFFIX} +find_library(RE2_SHARED_LIB NAMES ${RE2_SHARED_LIB_NAME} PATHS ${_re2_path} NO_DEFAULT_PATH PATH_SUFFIXES ${lib_dirs} diff --git a/cpp/src/arrow/util/bit-util-test.cc b/cpp/src/arrow/util/bit-util-test.cc index 5f181e9b7b1..8d2d0d2935c 100644 --- a/cpp/src/arrow/util/bit-util-test.cc +++ b/cpp/src/arrow/util/bit-util-test.cc @@ -734,6 +734,30 @@ TEST(BitUtil, CountLeadingZeros) { EXPECT_EQ(BitUtil::CountLeadingZeros(U64(ULLONG_MAX)), 0); } +TEST(BitUtil, CountTrailingZeros) { + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(0)), 32); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(1) << 31), 31); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(1) << 30), 30); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(1) << 29), 29); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(1) << 28), 28); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(8)), 3); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(4)), 2); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(2)), 1); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(1)), 0); + EXPECT_EQ(BitUtil::CountTrailingZeros(U32(ULONG_MAX)), 0); + + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(0)), 64); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(1) << 63), 63); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(1) << 62), 62); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(1) << 61), 61); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(1) << 60), 60); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(8)), 3); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(4)), 2); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(2)), 1); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(1)), 0); + EXPECT_EQ(BitUtil::CountTrailingZeros(U64(ULLONG_MAX)), 0); +} + #undef U32 #undef U64 diff --git a/cpp/src/arrow/util/bit-util.h b/cpp/src/arrow/util/bit-util.h index 93b6cb28d91..c081b10629e 100644 --- a/cpp/src/arrow/util/bit-util.h +++ b/cpp/src/arrow/util/bit-util.h @@ -45,6 +45,7 @@ #if defined(_MSC_VER) #include #pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) #define ARROW_BYTE_SWAP64 _byteswap_uint64 #define ARROW_BYTE_SWAP32 _byteswap_ulong #else @@ -183,6 +184,48 @@ static inline int CountLeadingZeros(uint64_t value) { #endif } +static inline int CountTrailingZeros(uint32_t value) { +#if defined(__clang__) || defined(__GNUC__) + if (value == 0) return 32; + return static_cast(__builtin_ctzl(value)); +#elif defined(_MSC_VER) + unsigned long index; // NOLINT + if (_BitScanForward(&index, value)) { + return static_cast(index); + } else { + return 32; + } +#else + int bitpos = 0; + while (value != 0) { + value >>= 1; + ++bitpos; + } + return bitpos; +#endif +} + +static inline int CountTrailingZeros(uint64_t value) { +#if defined(__clang__) || defined(__GNUC__) + if (value == 0) return 64; + return static_cast(__builtin_ctzll(value)); +#elif defined(_MSC_VER) + unsigned long index; // NOLINT + if (_BitScanForward64(&index, value)) { + return static_cast(index); + } else { + return 64; + } +#else + int bitpos = 0; + while (value != 0) { + value >>= 1; + ++bitpos; + } + return bitpos; +#endif +} + // Returns the minimum number of bits needed to represent an unsigned value static inline int NumRequiredBits(uint64_t x) { return 64 - CountLeadingZeros(x); } diff --git a/cpp/src/arrow/util/visibility.h b/cpp/src/arrow/util/visibility.h index 34aa752fd21..035d53a6bf8 100644 --- a/cpp/src/arrow/util/visibility.h +++ b/cpp/src/arrow/util/visibility.h @@ -20,6 +20,7 @@ #if defined(_WIN32) || defined(__CYGWIN__) #if defined(_MSC_VER) +#pragma warning(push) #pragma warning(disable : 4251) #else #pragma GCC diagnostic ignored "-Wattributes" diff --git a/cpp/src/gandiva/CMakeLists.txt b/cpp/src/gandiva/CMakeLists.txt index 6b67c8699c5..e04f8ccdede 100644 --- a/cpp/src/gandiva/CMakeLists.txt +++ b/cpp/src/gandiva/CMakeLists.txt @@ -43,29 +43,29 @@ configure_file(bc_file_path.cc.in ${BC_FILE_PATH_CC}) add_definitions(-DGANDIVA_BYTE_COMPILE_FILE_PATH="${GANDIVA_BC_OUTPUT_PATH}") set(SRC_FILES annotator.cc - bitmap_accumulator.cc - configuration.cc - context_helper.cc - engine.cc - date_utils.cc - expr_decomposer.cc - expr_validator.cc - expression.cc - expression_registry.cc - exported_funcs_registry.cc - filter.cc - function_registry.cc - function_signature.cc - gdv_function_stubs.cc - llvm_generator.cc - llvm_types.cc - like_holder.cc - projector.cc - regex_util.cc - selection_vector.cc - tree_expr_builder.cc - to_date_holder.cc - ${BC_FILE_PATH_CC}) + bitmap_accumulator.cc + configuration.cc + context_helper.cc + engine.cc + date_utils.cc + expr_decomposer.cc + expr_validator.cc + expression.cc + expression_registry.cc + exported_funcs_registry.cc + filter.cc + function_registry.cc + function_signature.cc + gdv_function_stubs.cc + llvm_generator.cc + llvm_types.cc + like_holder.cc + projector.cc + regex_util.cc + selection_vector.cc + tree_expr_builder.cc + to_date_holder.cc + ${BC_FILE_PATH_CC}) set(GANDIVA_SHARED_PRIVATE_LINK_LIBS arrow_shared @@ -95,6 +95,15 @@ ADD_ARROW_LIB(gandiva SHARED_PRIVATE_LINK_LIBS ${GANDIVA_SHARED_PRIVATE_LINK_LIBS} STATIC_LINK_LIBS ${GANDIVA_STATIC_LINK_LIBS}) +foreach(LIB_TARGET ${GANDIVA_LIBRARIES}) + target_compile_definitions(${LIB_TARGET} + PRIVATE GANDIVA_EXPORTING) +endforeach() + +if (ARROW_BUILD_STATIC AND WIN32) + target_compile_definitions(gandiva_static PUBLIC GANDIVA_STATIC) +endif() + add_dependencies(gandiva ${GANDIVA_LIBRARIES}) # install for gandiva diff --git a/cpp/src/gandiva/annotator.h b/cpp/src/gandiva/annotator.h index 6c2cd05b04e..c0ddc024635 100644 --- a/cpp/src/gandiva/annotator.h +++ b/cpp/src/gandiva/annotator.h @@ -27,12 +27,13 @@ #include "gandiva/eval_batch.h" #include "gandiva/gandiva_aliases.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief annotate the arrow fields in an expression, and use that /// to convert the incoming arrow-format row batch to an EvalBatch. -class Annotator { +class GANDIVA_EXPORT Annotator { public: Annotator() : buffer_count_(0), local_bitmap_count_(0) {} diff --git a/cpp/src/gandiva/bitmap_accumulator.h b/cpp/src/gandiva/bitmap_accumulator.h index 157405d680e..15a2044b5fd 100644 --- a/cpp/src/gandiva/bitmap_accumulator.h +++ b/cpp/src/gandiva/bitmap_accumulator.h @@ -24,12 +24,13 @@ #include "gandiva/dex.h" #include "gandiva/dex_visitor.h" #include "gandiva/eval_batch.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Extract bitmap buffer from either the input/buffer vectors or the /// local validity bitmap, and accumultes them to do the final computation. -class BitMapAccumulator : public DexDefaultVisitor { +class GANDIVA_EXPORT BitMapAccumulator : public DexDefaultVisitor { public: explicit BitMapAccumulator(const EvalBatch& eval_batch) : eval_batch_(eval_batch), all_invalid_(false) {} diff --git a/cpp/src/gandiva/bitmap_accumulator_test.cc b/cpp/src/gandiva/bitmap_accumulator_test.cc index 53e8aaca21f..51a8b09ec72 100644 --- a/cpp/src/gandiva/bitmap_accumulator_test.cc +++ b/cpp/src/gandiva/bitmap_accumulator_test.cc @@ -21,24 +21,22 @@ #include #include + +#include "arrow/test-util.h" + #include "gandiva/dex.h" namespace gandiva { class TestBitMapAccumulator : public ::testing::Test { protected: - void FillBitMap(uint8_t* bmap, int nrecords); + void FillBitMap(uint8_t* bmap, uint32_t seed, int nrecords); void ByteWiseIntersectBitMaps(uint8_t* dst, const std::vector& srcs, int nrecords); }; -void TestBitMapAccumulator::FillBitMap(uint8_t* bmap, int nbytes) { - unsigned int cur = 0; - - for (int i = 0; i < nbytes; ++i) { - rand_r(&cur); - bmap[i] = static_cast(cur % UINT8_MAX); - } +void TestBitMapAccumulator::FillBitMap(uint8_t* bmap, uint32_t seed, int nbytes) { + ::arrow::random_bytes(nbytes, seed, bmap); } void TestBitMapAccumulator::ByteWiseIntersectBitMaps(uint8_t* dst, @@ -61,7 +59,7 @@ TEST_F(TestBitMapAccumulator, TestIntersectBitMaps) { uint8_t expected_bitmap[length]; for (int i = 0; i < 4; i++) { - FillBitMap(src_bitmaps[i], length); + FillBitMap(src_bitmaps[i], i, length); } for (int i = 0; i < 4; i++) { diff --git a/cpp/src/gandiva/compiled_expr.h b/cpp/src/gandiva/compiled_expr.h index 2f23971f366..b7799f18928 100644 --- a/cpp/src/gandiva/compiled_expr.h +++ b/cpp/src/gandiva/compiled_expr.h @@ -18,7 +18,7 @@ #ifndef GANDIVA_COMPILED_EXPR_H #define GANDIVA_COMPILED_EXPR_H -#include +#include "gandiva/llvm_includes.h" #include "gandiva/value_validity_pair.h" namespace gandiva { diff --git a/cpp/src/gandiva/configuration.h b/cpp/src/gandiva/configuration.h index 04e2eed287e..480a95e9274 100644 --- a/cpp/src/gandiva/configuration.h +++ b/cpp/src/gandiva/configuration.h @@ -15,16 +15,18 @@ // specific language governing permissions and limitations // under the License. -#ifndef GANDIVA_CONFIGURATION_H -#define GANDIVA_CONFIGURATION_H +#pragma once #include #include #include "arrow/status.h" +#include "gandiva/visibility.h" + namespace gandiva { +GANDIVA_EXPORT extern const char kByteCodeFilePath[]; class ConfigurationBuilder; @@ -32,7 +34,7 @@ class ConfigurationBuilder; /// /// It contains elements to customize gandiva execution /// at run time. -class Configuration { +class GANDIVA_EXPORT Configuration { public: friend class ConfigurationBuilder; @@ -53,7 +55,7 @@ class Configuration { /// /// Provides a default configuration and convenience methods /// to override specific values and build a custom instance -class ConfigurationBuilder { +class GANDIVA_EXPORT ConfigurationBuilder { public: ConfigurationBuilder() : byte_code_file_path_(kByteCodeFilePath) {} @@ -83,4 +85,3 @@ class ConfigurationBuilder { }; } // namespace gandiva -#endif // GANDIVA_CONFIGURATION_H diff --git a/cpp/src/gandiva/date_utils.cc b/cpp/src/gandiva/date_utils.cc index 8a7e1f03fbd..6e6baea1996 100644 --- a/cpp/src/gandiva/date_utils.cc +++ b/cpp/src/gandiva/date_utils.cc @@ -16,6 +16,7 @@ // under the License. #include +#include #include #include #include @@ -57,7 +58,7 @@ Status DateUtils::ToInternalFormat(const std::string& format, std::stringstream buffer; bool is_in_quoted_text = false; - for (uint i = 0; i < format.length(); i++) { + for (int i = 0; i < format.length(); i++) { char currentChar = format[i]; // logic before we append to the buffer diff --git a/cpp/src/gandiva/date_utils.h b/cpp/src/gandiva/date_utils.h index 64a150b6ba7..2ebc7cac141 100644 --- a/cpp/src/gandiva/date_utils.h +++ b/cpp/src/gandiva/date_utils.h @@ -23,12 +23,22 @@ #include #include +#if defined(_MSC_VER) +#include +#include +#include +#endif + +#include "arrow/vendored/date.h" +#include "arrow/util/macros.h" + #include "gandiva/arrow.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Utility class for converting sql date patterns to internal date patterns. -class DateUtils { +class GANDIVA_EXPORT DateUtils { public: static Status ToInternalFormat(const std::string& format, std::shared_ptr* internal_format); @@ -47,6 +57,38 @@ class DateUtils { static std::vector GetExactMatches(const std::string& pattern); }; +namespace internal { + +/// \brief Returns seconds since the UNIX epoch +static inline bool ParseTimestamp(const char* buf, const char* format, int64_t* out) { +#if defined(_MSC_VER) + static std::locale lc_all(setlocale(LC_ALL, NULLPTR)); + std::istringstream stream(buf); + stream.imbue(lc_all); + + date::sys_seconds secs; + stream >> date::parse(format, secs); + if (stream.fail()) { + return false; + } + + *out = secs.time_since_epoch().count(); + return true; +#else + struct tm result; + char* ret = strptime(buf, format, &result); + if (ret == NULLPTR) { + return false; + } + // ignore the time part + *out = date::sys_days(date::year(result.tm_year + 1900) / (result.tm_mon + 1) / + result.tm_mday); + *out = secs.time_since_epoch().count(); + return true; +#endif +} + +} // namespace internal } // namespace gandiva #endif // TO_DATE_HELPER_H diff --git a/cpp/src/gandiva/dex.h b/cpp/src/gandiva/dex.h index afce44ed12f..894d9611058 100644 --- a/cpp/src/gandiva/dex.h +++ b/cpp/src/gandiva/dex.h @@ -32,11 +32,12 @@ #include "gandiva/literal_holder.h" #include "gandiva/native_function.h" #include "gandiva/value_validity_pair.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Decomposed expression : the validity and value are separated. -class Dex { +class GANDIVA_EXPORT Dex { public: /// Derived classes should simply invoke the Visit api of the visitor. virtual void Accept(DexVisitor& visitor) = 0; @@ -44,7 +45,7 @@ class Dex { }; /// Base class for other Vector related Dex. -class VectorReadBaseDex : public Dex { +class GANDIVA_EXPORT VectorReadBaseDex : public Dex { public: explicit VectorReadBaseDex(FieldDescriptorPtr field_desc) : field_desc_(field_desc) {} @@ -59,7 +60,7 @@ class VectorReadBaseDex : public Dex { }; /// validity component of a ValueVector -class VectorReadValidityDex : public VectorReadBaseDex { +class GANDIVA_EXPORT VectorReadValidityDex : public VectorReadBaseDex { public: explicit VectorReadValidityDex(FieldDescriptorPtr field_desc) : VectorReadBaseDex(field_desc) {} @@ -70,7 +71,7 @@ class VectorReadValidityDex : public VectorReadBaseDex { }; /// value component of a fixed-len ValueVector -class VectorReadFixedLenValueDex : public VectorReadBaseDex { +class GANDIVA_EXPORT VectorReadFixedLenValueDex : public VectorReadBaseDex { public: explicit VectorReadFixedLenValueDex(FieldDescriptorPtr field_desc) : VectorReadBaseDex(field_desc) {} @@ -81,7 +82,7 @@ class VectorReadFixedLenValueDex : public VectorReadBaseDex { }; /// value component of a variable-len ValueVector -class VectorReadVarLenValueDex : public VectorReadBaseDex { +class GANDIVA_EXPORT VectorReadVarLenValueDex : public VectorReadBaseDex { public: explicit VectorReadVarLenValueDex(FieldDescriptorPtr field_desc) : VectorReadBaseDex(field_desc) {} @@ -94,7 +95,7 @@ class VectorReadVarLenValueDex : public VectorReadBaseDex { }; /// validity based on a local bitmap. -class LocalBitMapValidityDex : public Dex { +class GANDIVA_EXPORT LocalBitMapValidityDex : public Dex { public: explicit LocalBitMapValidityDex(int local_bitmap_idx) : local_bitmap_idx_(local_bitmap_idx) {} @@ -108,7 +109,7 @@ class LocalBitMapValidityDex : public Dex { }; /// base function expression -class FuncDex : public Dex { +class GANDIVA_EXPORT FuncDex : public Dex { public: FuncDex(FuncDescriptorPtr func_descriptor, const NativeFunction* native_function, FunctionHolderPtr function_holder, const ValueValidityPairVector& args) @@ -134,7 +135,7 @@ class FuncDex : public Dex { /// A function expression that only deals with non-null inputs, and generates non-null /// outputs. -class NonNullableFuncDex : public FuncDex { +class GANDIVA_EXPORT NonNullableFuncDex : public FuncDex { public: NonNullableFuncDex(FuncDescriptorPtr func_descriptor, const NativeFunction* native_function, @@ -147,7 +148,7 @@ class NonNullableFuncDex : public FuncDex { /// A function expression that deals with nullable inputs, but generates non-null /// outputs. -class NullableNeverFuncDex : public FuncDex { +class GANDIVA_EXPORT NullableNeverFuncDex : public FuncDex { public: NullableNeverFuncDex(FuncDescriptorPtr func_descriptor, const NativeFunction* native_function, @@ -160,7 +161,7 @@ class NullableNeverFuncDex : public FuncDex { /// A function expression that deals with nullable inputs, and /// nullable outputs. -class NullableInternalFuncDex : public FuncDex { +class GANDIVA_EXPORT NullableInternalFuncDex : public FuncDex { public: NullableInternalFuncDex(FuncDescriptorPtr func_descriptor, const NativeFunction* native_function, @@ -179,17 +180,17 @@ class NullableInternalFuncDex : public FuncDex { }; /// special validity type that always returns true. -class TrueDex : public Dex { +class GANDIVA_EXPORT TrueDex : public Dex { void Accept(DexVisitor& visitor) override { visitor.Visit(*this); } }; /// special validity type that always returns false. -class FalseDex : public Dex { +class GANDIVA_EXPORT FalseDex : public Dex { void Accept(DexVisitor& visitor) override { visitor.Visit(*this); } }; /// decomposed expression for a literal. -class LiteralDex : public Dex { +class GANDIVA_EXPORT LiteralDex : public Dex { public: LiteralDex(DataTypePtr type, const LiteralHolder& holder) : type_(type), holder_(holder) {} @@ -206,7 +207,7 @@ class LiteralDex : public Dex { }; /// decomposed if-else expression. -class IfDex : public Dex { +class GANDIVA_EXPORT IfDex : public Dex { public: IfDex(ValueValidityPairPtr condition_vv, ValueValidityPairPtr then_vv, ValueValidityPairPtr else_vv, DataTypePtr result_type, int local_bitmap_idx, @@ -242,7 +243,7 @@ class IfDex : public Dex { }; // decomposed boolean expression. -class BooleanDex : public Dex { +class GANDIVA_EXPORT BooleanDex : public Dex { public: BooleanDex(const ValueValidityPairVector& args, int local_bitmap_idx) : args_(args), local_bitmap_idx_(local_bitmap_idx) {} @@ -258,7 +259,7 @@ class BooleanDex : public Dex { }; /// Boolean-AND expression -class BooleanAndDex : public BooleanDex { +class GANDIVA_EXPORT BooleanAndDex : public BooleanDex { public: BooleanAndDex(const ValueValidityPairVector& args, int local_bitmap_idx) : BooleanDex(args, local_bitmap_idx) {} @@ -267,7 +268,7 @@ class BooleanAndDex : public BooleanDex { }; /// Boolean-OR expression -class BooleanOrDex : public BooleanDex { +class GANDIVA_EXPORT BooleanOrDex : public BooleanDex { public: BooleanOrDex(const ValueValidityPairVector& args, int local_bitmap_idx) : BooleanDex(args, local_bitmap_idx) {} diff --git a/cpp/src/gandiva/dex_visitor.h b/cpp/src/gandiva/dex_visitor.h index 456fe430511..c34629a53e1 100644 --- a/cpp/src/gandiva/dex_visitor.h +++ b/cpp/src/gandiva/dex_visitor.h @@ -21,6 +21,7 @@ #include #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -41,7 +42,7 @@ template class InExprDexBase; /// \brief Visitor for decomposed expression. -class DexVisitor { +class GANDIVA_EXPORT DexVisitor { public: virtual ~DexVisitor() = default; @@ -67,7 +68,7 @@ class DexVisitor { #define VISIT_DCHECK(DEX_CLASS) \ void Visit(const DEX_CLASS& dex) override { DCHECK(0); } -class DexDefaultVisitor : public DexVisitor { +class GANDIVA_EXPORT DexDefaultVisitor : public DexVisitor { VISIT_DCHECK(VectorReadValidityDex) VISIT_DCHECK(VectorReadFixedLenValueDex) VISIT_DCHECK(VectorReadVarLenValueDex) diff --git a/cpp/src/gandiva/engine.cc b/cpp/src/gandiva/engine.cc index da7a6d886c0..552d14acf25 100644 --- a/cpp/src/gandiva/engine.cc +++ b/cpp/src/gandiva/engine.cc @@ -23,6 +23,15 @@ #include #include +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4141) +#pragma warning(disable : 4146) +#pragma warning(disable : 4244) +#pragma warning(disable : 4267) +#pragma warning(disable : 4624) +#endif + #include #include #include @@ -39,6 +48,11 @@ #include #include #include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + #include "gandiva/exported_funcs_registry.h" namespace gandiva { diff --git a/cpp/src/gandiva/engine.h b/cpp/src/gandiva/engine.h index f377ebc38d3..924329cd48d 100644 --- a/cpp/src/gandiva/engine.h +++ b/cpp/src/gandiva/engine.h @@ -23,22 +23,19 @@ #include #include -#include -#include -#include -#include - #include "arrow/status.h" #include "arrow/util/macros.h" #include "gandiva/configuration.h" +#include "gandiva/llvm_includes.h" #include "gandiva/llvm_types.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief LLVM Execution engine wrapper. -class Engine { +class GANDIVA_EXPORT Engine { public: llvm::LLVMContext* context() { return context_.get(); } llvm::IRBuilder<>* ir_builder() { return ir_builder_.get(); } diff --git a/cpp/src/gandiva/expr_decomposer.cc b/cpp/src/gandiva/expr_decomposer.cc index bed84ededb5..91014f1b827 100644 --- a/cpp/src/gandiva/expr_decomposer.cc +++ b/cpp/src/gandiva/expr_decomposer.cc @@ -232,7 +232,7 @@ int ExprDecomposer::PushThenEntry(const IfNode& node) { // push new entry to the stack. std::unique_ptr entry(new IfStackEntry( node, kStackEntryThen, false /*is_terminal_else*/, local_bitmap_idx)); - if_entries_stack_.push(std::move(entry)); + if_entries_stack_.emplace(std::move(entry)); return local_bitmap_idx; } @@ -250,7 +250,7 @@ void ExprDecomposer::PopThenEntry(const IfNode& node) { void ExprDecomposer::PushElseEntry(const IfNode& node, int local_bitmap_idx) { std::unique_ptr entry(new IfStackEntry( node, kStackEntryElse, true /*is_terminal_else*/, local_bitmap_idx)); - if_entries_stack_.push(std::move(entry)); + if_entries_stack_.emplace(std::move(entry)); } bool ExprDecomposer::PopElseEntry(const IfNode& node) { @@ -268,7 +268,7 @@ bool ExprDecomposer::PopElseEntry(const IfNode& node) { void ExprDecomposer::PushConditionEntry(const IfNode& node) { std::unique_ptr entry(new IfStackEntry(node, kStackEntryCondition)); - if_entries_stack_.push(std::move(entry)); + if_entries_stack_.emplace(std::move(entry)); } void ExprDecomposer::PopConditionEntry(const IfNode& node) { diff --git a/cpp/src/gandiva/expr_decomposer.h b/cpp/src/gandiva/expr_decomposer.h index bc21ed07cf5..ab92ca3d249 100644 --- a/cpp/src/gandiva/expr_decomposer.h +++ b/cpp/src/gandiva/expr_decomposer.h @@ -27,6 +27,7 @@ #include "gandiva/expression.h" #include "gandiva/node.h" #include "gandiva/node_visitor.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -35,7 +36,7 @@ class Annotator; /// \brief Decomposes an expression tree to seperate out the validity and /// value expressions. -class ExprDecomposer : public NodeVisitor { +class GANDIVA_EXPORT ExprDecomposer : public NodeVisitor { public: explicit ExprDecomposer(const FunctionRegistry& registry, Annotator& annotator) : registry_(registry), annotator_(annotator) {} @@ -49,6 +50,8 @@ class ExprDecomposer : public NodeVisitor { } private: + ARROW_DISALLOW_COPY_AND_ASSIGN(ExprDecomposer); + FRIEND_TEST(TestExprDecomposer, TestStackSimple); FRIEND_TEST(TestExprDecomposer, TestNested); FRIEND_TEST(TestExprDecomposer, TestInternalIf); @@ -83,6 +86,9 @@ class ExprDecomposer : public NodeVisitor { StackEntryType entry_type_; bool is_terminal_else_; int local_bitmap_idx_; + + private: + ARROW_DISALLOW_COPY_AND_ASSIGN(IfStackEntry); }; // pop 'condition entry' into stack. diff --git a/cpp/src/gandiva/expression.h b/cpp/src/gandiva/expression.h index e3ae18f4d4c..2141e871393 100644 --- a/cpp/src/gandiva/expression.h +++ b/cpp/src/gandiva/expression.h @@ -22,11 +22,12 @@ #include "gandiva/arrow.h" #include "gandiva/gandiva_aliases.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief An expression tree with a root node, and a result field. -class Expression { +class GANDIVA_EXPORT Expression { public: Expression(const NodePtr root, const FieldPtr result) : root_(root), result_(result) {} diff --git a/cpp/src/gandiva/expression_registry.h b/cpp/src/gandiva/expression_registry.h index a03deab91cd..4524a077a62 100644 --- a/cpp/src/gandiva/expression_registry.h +++ b/cpp/src/gandiva/expression_registry.h @@ -24,6 +24,7 @@ #include "gandiva/arrow.h" #include "gandiva/function_signature.h" #include "gandiva/gandiva_aliases.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -33,13 +34,13 @@ class FunctionRegistry; /// /// Has helper methods for clients to programatically discover /// data types and functions supported by Gandiva. -class ExpressionRegistry { +class GANDIVA_EXPORT ExpressionRegistry { public: using iterator = const NativeFunction*; ExpressionRegistry(); ~ExpressionRegistry(); static DataTypeVector supported_types() { return supported_types_; } - class FunctionSignatureIterator { + class GANDIVA_EXPORT FunctionSignatureIterator { public: explicit FunctionSignatureIterator(iterator it) : it_(it) {} diff --git a/cpp/src/gandiva/filter.cc b/cpp/src/gandiva/filter.cc index 6075e257455..3bba1909af8 100644 --- a/cpp/src/gandiva/filter.cc +++ b/cpp/src/gandiva/filter.cc @@ -37,6 +37,8 @@ Filter::Filter(std::unique_ptr llvm_generator, SchemaPtr schema, schema_(schema), configuration_(configuration) {} +Filter::~Filter() {} + Status Filter::Make(SchemaPtr schema, ConditionPtr condition, std::shared_ptr configuration, std::shared_ptr* filter) { diff --git a/cpp/src/gandiva/filter.h b/cpp/src/gandiva/filter.h index 6ff7010ac07..4fbda806e0a 100644 --- a/cpp/src/gandiva/filter.h +++ b/cpp/src/gandiva/filter.h @@ -15,8 +15,7 @@ // specific language governing permissions and limitations // under the License. -#ifndef GANDIVA_EXPR_FILTER_H -#define GANDIVA_EXPR_FILTER_H +#pragma once #include #include @@ -29,6 +28,7 @@ #include "gandiva/condition.h" #include "gandiva/configuration.h" #include "gandiva/selection_vector.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -38,12 +38,14 @@ class LLVMGenerator; /// /// A filter is built for a specific schema and condition. Once the filter is built, it /// can be used to evaluate many row batches. -class Filter { +class GANDIVA_EXPORT Filter { public: Filter(std::unique_ptr llvm_generator, SchemaPtr schema, std::shared_ptr config); - ~Filter() = default; + // Inline dtor will attempt to resolve the destructor for + // LLVMGenerator on MSVC, so we compile the dtor in the object code + ~Filter(); /// Build a filter for the given schema and condition, with the default configuration. /// @@ -81,5 +83,3 @@ class Filter { }; } // namespace gandiva - -#endif // GANDIVA_EXPR_FILTER_H diff --git a/cpp/src/gandiva/func_descriptor.h b/cpp/src/gandiva/func_descriptor.h index 9b18a9b6943..08f719995fe 100644 --- a/cpp/src/gandiva/func_descriptor.h +++ b/cpp/src/gandiva/func_descriptor.h @@ -22,11 +22,12 @@ #include #include "gandiva/arrow.h" +#include "gandiva/visibility.h" namespace gandiva { /// Descriptor for a function in the expression. -class FuncDescriptor { +class GANDIVA_EXPORT FuncDescriptor { public: FuncDescriptor(const std::string& name, const DataTypeVector& params, DataTypePtr return_type) diff --git a/cpp/src/gandiva/function_holder.h b/cpp/src/gandiva/function_holder.h index 4d007d1db3f..43dbeac07c9 100644 --- a/cpp/src/gandiva/function_holder.h +++ b/cpp/src/gandiva/function_holder.h @@ -20,10 +20,12 @@ #include +#include "gandiva/visibility.h" + namespace gandiva { /// Holder for a function that can be invoked from LLVM. -class FunctionHolder { +class GANDIVA_EXPORT FunctionHolder { public: virtual ~FunctionHolder() = default; }; diff --git a/cpp/src/gandiva/function_registry.h b/cpp/src/gandiva/function_registry.h index 0f74089fc6d..7b4beecbf29 100644 --- a/cpp/src/gandiva/function_registry.h +++ b/cpp/src/gandiva/function_registry.h @@ -22,11 +22,12 @@ #include "gandiva/gandiva_aliases.h" #include "gandiva/native_function.h" +#include "gandiva/visibility.h" namespace gandiva { ///\brief Registry of pre-compiled IR functions. -class FunctionRegistry { +class GANDIVA_EXPORT FunctionRegistry { public: using iterator = const NativeFunction*; diff --git a/cpp/src/gandiva/function_signature.h b/cpp/src/gandiva/function_signature.h index e5dff245b15..be40e5820d2 100644 --- a/cpp/src/gandiva/function_signature.h +++ b/cpp/src/gandiva/function_signature.h @@ -24,12 +24,13 @@ #include "gandiva/arrow.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Signature for a function : includes the base name, input param types and /// output types. -class FunctionSignature { +class GANDIVA_EXPORT FunctionSignature { public: FunctionSignature(const std::string& base_name, const DataTypeVector& param_types, DataTypePtr ret_type) diff --git a/cpp/src/gandiva/like_holder.h b/cpp/src/gandiva/like_holder.h index 23ed367e8cc..eab30bf732f 100644 --- a/cpp/src/gandiva/like_holder.h +++ b/cpp/src/gandiva/like_holder.h @@ -22,14 +22,17 @@ #include #include + #include "arrow/status.h" + #include "gandiva/function_holder.h" #include "gandiva/node.h" +#include "gandiva/visibility.h" namespace gandiva { /// Function Holder for SQL 'like' -class LikeHolder : public FunctionHolder { +class GANDIVA_EXPORT LikeHolder : public FunctionHolder { public: ~LikeHolder() override = default; diff --git a/cpp/src/gandiva/llvm_generator.h b/cpp/src/gandiva/llvm_generator.h index 49f209d280d..baa997bf9d7 100644 --- a/cpp/src/gandiva/llvm_generator.h +++ b/cpp/src/gandiva/llvm_generator.h @@ -36,13 +36,14 @@ #include "gandiva/llvm_types.h" #include "gandiva/lvalue.h" #include "gandiva/value_validity_pair.h" +#include "gandiva/visibility.h" namespace gandiva { class FunctionHolder; /// Builds an LLVM module and generates code for the specified set of expressions. -class LLVMGenerator { +class GANDIVA_EXPORT LLVMGenerator { public: /// \brief Factory method to initialize the generator. static Status Make(std::shared_ptr config, diff --git a/cpp/src/gandiva/llvm_includes.h b/cpp/src/gandiva/llvm_includes.h new file mode 100644 index 00000000000..9de1f45a0ad --- /dev/null +++ b/cpp/src/gandiva/llvm_includes.h @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4141) +#pragma warning(disable : 4146) +#pragma warning(disable : 4244) +#pragma warning(disable : 4267) +#pragma warning(disable : 4291) +#pragma warning(disable : 4624) +#endif + +#include +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/cpp/src/gandiva/llvm_types.h b/cpp/src/gandiva/llvm_types.h index dab47d059f7..56f3299c5b0 100644 --- a/cpp/src/gandiva/llvm_types.h +++ b/cpp/src/gandiva/llvm_types.h @@ -21,15 +21,15 @@ #include #include -#include -#include #include "gandiva/arrow.h" +#include "gandiva/llvm_includes.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Holder for llvm types, and mappings between arrow types and llvm types. -class LLVMTypes { +class GANDIVA_EXPORT LLVMTypes { public: explicit LLVMTypes(llvm::LLVMContext& context); diff --git a/cpp/src/gandiva/lvalue.h b/cpp/src/gandiva/lvalue.h index 2ff03dcdd9c..0e7a44f3f0f 100644 --- a/cpp/src/gandiva/lvalue.h +++ b/cpp/src/gandiva/lvalue.h @@ -19,8 +19,7 @@ #define GANDIVA_LVALUE_H #include "arrow/util/macros.h" - -#include +#include "gandiva/llvm_includes.h" namespace gandiva { diff --git a/cpp/src/gandiva/native_function.h b/cpp/src/gandiva/native_function.h index 7a250e01cb6..c8e62e76563 100644 --- a/cpp/src/gandiva/native_function.h +++ b/cpp/src/gandiva/native_function.h @@ -23,6 +23,7 @@ #include #include "gandiva/function_signature.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -37,7 +38,7 @@ enum ResultNullableType { /// \brief Holder for the mapping from a function in an expression to a /// precompiled function. -class NativeFunction { +class GANDIVA_EXPORT NativeFunction { public: // fucntion attributes. static constexpr int32_t kNeedsContext = (1 << 1); diff --git a/cpp/src/gandiva/node.h b/cpp/src/gandiva/node.h index d31924aa730..e694c7e0a3c 100644 --- a/cpp/src/gandiva/node.h +++ b/cpp/src/gandiva/node.h @@ -30,12 +30,13 @@ #include "gandiva/gandiva_aliases.h" #include "gandiva/literal_holder.h" #include "gandiva/node_visitor.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Represents a node in the expression tree. Validity and value are /// in a joined state. -class Node { +class GANDIVA_EXPORT Node { public: explicit Node(DataTypePtr return_type) : return_type_(return_type) {} @@ -53,7 +54,7 @@ class Node { }; /// \brief Node in the expression tree, representing a literal. -class LiteralNode : public Node { +class GANDIVA_EXPORT LiteralNode : public Node { public: LiteralNode(DataTypePtr type, const LiteralHolder& holder, bool is_null) : Node(type), holder_(holder), is_null_(is_null) {} @@ -95,7 +96,7 @@ class LiteralNode : public Node { }; /// \brief Node in the expression tree, representing an arrow field. -class FieldNode : public Node { +class GANDIVA_EXPORT FieldNode : public Node { public: explicit FieldNode(FieldPtr field) : Node(field->type()), field_(field) {} @@ -112,7 +113,7 @@ class FieldNode : public Node { }; /// \brief Node in the expression tree, representing a function. -class FunctionNode : public Node { +class GANDIVA_EXPORT FunctionNode : public Node { public: FunctionNode(const std::string& name, const NodeVector& children, DataTypePtr retType); @@ -154,7 +155,7 @@ inline FunctionNode::FunctionNode(const std::string& name, const NodeVector& chi } /// \brief Node in the expression tree, representing an if-else expression. -class IfNode : public Node { +class GANDIVA_EXPORT IfNode : public Node { public: IfNode(NodePtr condition, NodePtr then_node, NodePtr else_node, DataTypePtr result_type) : Node(result_type), @@ -183,7 +184,7 @@ class IfNode : public Node { }; /// \brief Node in the expression tree, representing an and/or boolean expression. -class BooleanNode : public Node { +class GANDIVA_EXPORT BooleanNode : public Node { public: enum ExprType : char { AND, OR }; diff --git a/cpp/src/gandiva/node_visitor.h b/cpp/src/gandiva/node_visitor.h index ba3645a5896..27d05649b8e 100644 --- a/cpp/src/gandiva/node_visitor.h +++ b/cpp/src/gandiva/node_visitor.h @@ -23,6 +23,7 @@ #include "arrow/status.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -35,7 +36,7 @@ template class InExpressionNode; /// \brief Visitor for nodes in the expression tree. -class NodeVisitor { +class GANDIVA_EXPORT NodeVisitor { public: virtual ~NodeVisitor() = default; diff --git a/cpp/src/gandiva/precompiled/CMakeLists.txt b/cpp/src/gandiva/precompiled/CMakeLists.txt index 21a74bd4916..e81bcabbb17 100644 --- a/cpp/src/gandiva/precompiled/CMakeLists.txt +++ b/cpp/src/gandiva/precompiled/CMakeLists.txt @@ -27,6 +27,18 @@ set(PRECOMPILED_SRCS time.cc timestamp_arithmetic.cc) +if (MSVC) + # clang pretends to be a particular version of MSVC. Version 1900 is + # Visual Studio 2015, and the standard library uses C++14 features, + # so we have to use that -std version to get the IR compilation to + # work + set(PLATFORM_CLANG_OPTIONS + -std=c++14 -fms-compatibility -fms-compatibility-version=19) +else() + set(PLATFORM_CLANG_OPTIONS + -std=c++11) +endif() + # Create bitcode for each of the source files. foreach(SRC_FILE ${PRECOMPILED_SRCS}) get_filename_component(SRC_BASE ${SRC_FILE} NAME_WE) @@ -35,7 +47,8 @@ foreach(SRC_FILE ${PRECOMPILED_SRCS}) add_custom_command( OUTPUT ${BC_FILE} COMMAND ${CLANG_EXECUTABLE} - -std=c++11 -emit-llvm -O2 -c ${ABSOLUTE_SRC} -o ${BC_FILE} + ${PLATFORM_CLANG_OPTIONS} + -emit-llvm -O2 -c ${ABSOLUTE_SRC} -o ${BC_FILE} -I${CMAKE_SOURCE_DIR}/src DEPENDS ${SRC_FILE}) list(APPEND BC_FILES ${BC_FILE}) @@ -58,14 +71,17 @@ function(add_precompiled_unit_test REL_TEST_NAME) set(TEST_NAME "gandiva-precompiled-${TEST_NAME}") add_executable(${TEST_NAME} ${REL_TEST_NAME} ${ARGN}) - add_dependencies(gandiva-tests ${TEST_NAME}) target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src) target_link_libraries(${TEST_NAME} PRIVATE ${ARROW_TEST_LINK_LIBS} ${RE2_LIBRARY} ) target_compile_definitions(${TEST_NAME} PRIVATE GANDIVA_UNIT_TEST=1) - add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) - set_property(TEST ${TEST_NAME} PROPERTY LABELS gandiva-tests {TEST_NAME}) + set(TEST_PATH "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}") + add_test(${TEST_NAME} ${TEST_PATH}) + set_property(TEST ${TEST_NAME} + APPEND PROPERTY + LABELS "unittest;gandiva-tests") + add_dependencies(gandiva-tests ${TEST_NAME}) endfunction(add_precompiled_unit_test REL_TEST_NAME) # testing diff --git a/cpp/src/gandiva/precompiled/epoch_time_point_test.cc b/cpp/src/gandiva/precompiled/epoch_time_point_test.cc index f489b7d748c..32cb9e87fe2 100644 --- a/cpp/src/gandiva/precompiled/epoch_time_point_test.cc +++ b/cpp/src/gandiva/precompiled/epoch_time_point_test.cc @@ -15,36 +15,39 @@ // specific language governing permissions and limitations // under the License. -#include +#include #include #include "./epoch_time_point.h" +#include "gandiva/precompiled/testing.h" #include "gandiva/precompiled/types.h" -namespace gandiva { +#include "gandiva/date_utils.h" -timestamp StringToTimestamp(const char* buf) { - struct tm tm; - strptime(buf, "%Y-%m-%d %H:%M:%S", &tm); - return timegm(&tm) * 1000; // to millis -} +namespace gandiva { TEST(TestEpochTimePoint, TestTm) { auto ts = StringToTimestamp("2015-05-07 10:20:34"); EpochTimePoint tp(ts); + struct tm* tm_ptr; +#if defined(_MSC_VER) + __time64_t tsec = ts / 1000; + tm_ptr = _gmtime64(&tsec); +#else struct tm tm; time_t tsec = ts / 1000; - gmtime_r(&tsec, &tm); - - EXPECT_EQ(tp.TmYear(), tm.tm_year); - EXPECT_EQ(tp.TmMon(), tm.tm_mon); - EXPECT_EQ(tp.TmYday(), tm.tm_yday); - EXPECT_EQ(tp.TmMday(), tm.tm_mday); - EXPECT_EQ(tp.TmWday(), tm.tm_wday); - EXPECT_EQ(tp.TmHour(), tm.tm_hour); - EXPECT_EQ(tp.TmMin(), tm.tm_min); - EXPECT_EQ(tp.TmSec(), tm.tm_sec); + tm_ptr = gmtime_r(&tsec, &tm); +#endif + + EXPECT_EQ(tp.TmYear(), tm_ptr->tm_year); + EXPECT_EQ(tp.TmMon(), tm_ptr->tm_mon); + EXPECT_EQ(tp.TmYday(), tm_ptr->tm_yday); + EXPECT_EQ(tp.TmMday(), tm_ptr->tm_mday); + EXPECT_EQ(tp.TmWday(), tm_ptr->tm_wday); + EXPECT_EQ(tp.TmHour(), tm_ptr->tm_hour); + EXPECT_EQ(tp.TmMin(), tm_ptr->tm_min); + EXPECT_EQ(tp.TmSec(), tm_ptr->tm_sec); } TEST(TestEpochTimePoint, TestAddYears) { diff --git a/cpp/src/gandiva/precompiled/extended_math_ops.cc b/cpp/src/gandiva/precompiled/extended_math_ops.cc index 1b7642cc3b3..b17ccd8e80a 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops.cc @@ -33,30 +33,40 @@ extern "C" { INNER(float64, OUT_TYPE) // Cubic root -#define CBRT(IN_TYPE, OUT_TYPE) \ - FORCE_INLINE \ - OUT_TYPE cbrt_##IN_TYPE(IN_TYPE in) { return static_cast(cbrtl(in)); } +#define CBRT(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + OUT_TYPE cbrt_##IN_TYPE(IN_TYPE in) { \ + return static_cast(cbrtl(static_cast(in))); \ + } ENUMERIC_TYPES_UNARY(CBRT, float64) // Exponent -#define EXP(IN_TYPE, OUT_TYPE) \ - FORCE_INLINE \ - OUT_TYPE exp_##IN_TYPE(IN_TYPE in) { return static_cast(expl(in)); } +#define EXP(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + OUT_TYPE exp_##IN_TYPE(IN_TYPE in) { \ + return static_cast(expl(static_cast(in))); \ + } ENUMERIC_TYPES_UNARY(EXP, float64) // log -#define LOG(IN_TYPE, OUT_TYPE) \ - FORCE_INLINE \ - OUT_TYPE log_##IN_TYPE(IN_TYPE in) { return static_cast(logl(in)); } +#define LOG(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + OUT_TYPE log_##IN_TYPE(IN_TYPE in) { \ + return static_cast(logl(static_cast(in))); \ + } ENUMERIC_TYPES_UNARY(LOG, float64) // log base 10 -#define LOG10(IN_TYPE, OUT_TYPE) \ - FORCE_INLINE \ - OUT_TYPE log10_##IN_TYPE(IN_TYPE in) { return static_cast(log10l(in)); } +#define LOG10(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + OUT_TYPE log10_##IN_TYPE(IN_TYPE in) { \ + return static_cast(log10l(static_cast(in))); \ + } + +#define LOGL(VALUE) static_cast(logl(static_cast(VALUE))) ENUMERIC_TYPES_UNARY(LOG10, float64) @@ -74,12 +84,12 @@ void set_error_for_logbase(int64_t execution_context, double base) { #define LOG_WITH_BASE(IN_TYPE1, IN_TYPE2, OUT_TYPE) \ FORCE_INLINE \ OUT_TYPE log_##IN_TYPE1##_##IN_TYPE2(int64 context, IN_TYPE1 base, IN_TYPE2 value) { \ - OUT_TYPE log_of_base = static_cast(logl(base)); \ + OUT_TYPE log_of_base = LOGL(base); \ if (log_of_base == 0) { \ set_error_for_logbase(context, static_cast(base)); \ return 0; \ } \ - return static_cast(logl(value) / logl(base)); \ + return LOGL(value) / LOGL(base); \ } LOG_WITH_BASE(int32, int32, float64) diff --git a/cpp/src/gandiva/precompiled/testing.h b/cpp/src/gandiva/precompiled/testing.h new file mode 100644 index 00000000000..79b021f5af4 --- /dev/null +++ b/cpp/src/gandiva/precompiled/testing.h @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include + +#include +#include "gandiva/date_utils.h" +#include "gandiva/precompiled/types.h" + +namespace gandiva { + +timestamp StringToTimestamp(const char* buf) { + int64_t out = 0; + ARROW_UNUSED(internal::ParseTimestamp(buf, "%Y-%m-%d %H:%M:%S", &out)); + return out * 1000; +} + +} // namespace gandiva diff --git a/cpp/src/gandiva/precompiled/time_test.cc b/cpp/src/gandiva/precompiled/time_test.cc index b8ee4dc4fbe..6fd4fce27d3 100644 --- a/cpp/src/gandiva/precompiled/time_test.cc +++ b/cpp/src/gandiva/precompiled/time_test.cc @@ -19,16 +19,11 @@ #include #include "../execution_context.h" +#include "gandiva/precompiled/testing.h" #include "gandiva/precompiled/types.h" namespace gandiva { -timestamp StringToTimestamp(const char* buf) { - struct tm tm; - strptime(buf, "%Y-%m-%d %H:%M:%S", &tm); - return timegm(&tm) * 1000; // to millis -} - TEST(TestTime, TestCastDate) { ExecutionContext context; int64_t context_ptr = reinterpret_cast(&context); diff --git a/cpp/src/gandiva/projector.cc b/cpp/src/gandiva/projector.cc index 4cb352f2ad3..a40dd7c4b73 100644 --- a/cpp/src/gandiva/projector.cc +++ b/cpp/src/gandiva/projector.cc @@ -36,6 +36,8 @@ Projector::Projector(std::unique_ptr llvm_generator, SchemaPtr sc output_fields_(output_fields), configuration_(configuration) {} +Projector::~Projector() {} + Status Projector::Make(SchemaPtr schema, const ExpressionVector& exprs, std::shared_ptr* projector) { return Projector::Make(schema, exprs, ConfigurationBuilder::DefaultConfiguration(), diff --git a/cpp/src/gandiva/projector.h b/cpp/src/gandiva/projector.h index c9d72716473..58bac78a406 100644 --- a/cpp/src/gandiva/projector.h +++ b/cpp/src/gandiva/projector.h @@ -15,8 +15,7 @@ // specific language governing permissions and limitations // under the License. -#ifndef GANDIVA_EXPR_PROJECTOR_H -#define GANDIVA_EXPR_PROJECTOR_H +#pragma once #include #include @@ -28,6 +27,7 @@ #include "gandiva/arrow.h" #include "gandiva/configuration.h" #include "gandiva/expression.h" +#include "gandiva/visibility.h" namespace gandiva { @@ -37,8 +37,12 @@ class LLVMGenerator; /// /// A projector is built for a specific schema and vector of expressions. /// Once the projector is built, it can be used to evaluate many row batches. -class Projector { +class GANDIVA_EXPORT Projector { public: + // Inline dtor will attempt to resolve the destructor for + // LLVMGenerator on MSVC, so we compile the dtor in the object code + ~Projector(); + /// Build a default projector for the given schema to evaluate /// the vector of expressions. /// @@ -99,5 +103,3 @@ class Projector { }; } // namespace gandiva - -#endif // GANDIVA_EXPR_PROJECTOR_H diff --git a/cpp/src/gandiva/regex_util.h b/cpp/src/gandiva/regex_util.h index 6a22af2b9ca..7ea7060c483 100644 --- a/cpp/src/gandiva/regex_util.h +++ b/cpp/src/gandiva/regex_util.h @@ -23,11 +23,12 @@ #include #include "gandiva/arrow.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Utility class for converting sql patterns to pcre patterns. -class RegexUtil { +class GANDIVA_EXPORT RegexUtil { public: // Convert an sql pattern to a pcre pattern static Status SqlLikePatternToPcre(const std::string& like_pattern, char escape_char, diff --git a/cpp/src/gandiva/selection_vector.cc b/cpp/src/gandiva/selection_vector.cc index f89b80c2b51..e643cece8a2 100644 --- a/cpp/src/gandiva/selection_vector.cc +++ b/cpp/src/gandiva/selection_vector.cc @@ -22,6 +22,8 @@ #include #include +#include "arrow/util/bit-util.h" + #include "gandiva/selection_vector_impl.h" namespace gandiva { @@ -48,8 +50,18 @@ Status SelectionVector::PopulateFromBitMap(const uint8_t* bitmap, int64_t bitmap uint64_t current_word = bitmap_64[bitmap_idx]; while (current_word != 0) { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + // MSVC warns about negating an unsigned type. We suppress it for now uint64_t highest_only = current_word & -current_word; - int pos_in_word = __builtin_ctzl(highest_only); + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + int pos_in_word = arrow::BitUtil::CountTrailingZeros(highest_only); int64_t pos_in_bitmap = bitmap_idx * 64 + pos_in_word; if (pos_in_bitmap > max_bitmap_index) { diff --git a/cpp/src/gandiva/selection_vector.h b/cpp/src/gandiva/selection_vector.h index dcd2f6bbb7f..2e9941781d0 100644 --- a/cpp/src/gandiva/selection_vector.h +++ b/cpp/src/gandiva/selection_vector.h @@ -24,12 +24,13 @@ #include "gandiva/arrow.h" #include "gandiva/logging.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Selection Vector : vector of indices in a row-batch for a selection, /// backed by an arrow-array. -class SelectionVector { +class GANDIVA_EXPORT SelectionVector { public: virtual ~SelectionVector() = default; diff --git a/cpp/src/gandiva/tests/date_time_test.cc b/cpp/src/gandiva/tests/date_time_test.cc index 643b8c8dda3..7867a9500fd 100644 --- a/cpp/src/gandiva/tests/date_time_test.cc +++ b/cpp/src/gandiva/tests/date_time_test.cc @@ -57,7 +57,7 @@ int64_t MillisSince(time_t base_line, int32_t yy, int32_t mm, int32_t dd, int32_ given_ts.tm_min = min; given_ts.tm_sec = sec; - return (lround(difftime(mktime(&given_ts), base_line)) * 1000 + millis); + return (static_cast(difftime(mktime(&given_ts), base_line)) * 1000 + millis); } TEST_F(TestProjector, TestIsNull) { diff --git a/cpp/src/gandiva/to_date_holder.cc b/cpp/src/gandiva/to_date_holder.cc index b512934e233..b26cd691ada 100644 --- a/cpp/src/gandiva/to_date_holder.cc +++ b/cpp/src/gandiva/to_date_holder.cc @@ -64,8 +64,7 @@ Status ToDateHolder::Make(const FunctionNode& node, Status ToDateHolder::Make(const std::string& sql_pattern, int32_t suppress_errors, std::shared_ptr* holder) { std::shared_ptr transformed_pattern; - Status status = DateUtils::ToInternalFormat(sql_pattern, &transformed_pattern); - ARROW_RETURN_NOT_OK(status); + ARROW_RETURN_NOT_OK(DateUtils::ToInternalFormat(sql_pattern, &transformed_pattern)); auto lholder = std::shared_ptr( new ToDateHolder(*(transformed_pattern.get()), suppress_errors)); *holder = lholder; @@ -82,21 +81,15 @@ int64_t ToDateHolder::operator()(ExecutionContext* context, const std::string& d // Issues // 1. processes date that do not match the format. // 2. does not process time in format +08:00 (or) id. - struct tm result = {}; - char* ret = strptime(data.c_str(), pattern_.c_str(), &result); - if (ret == nullptr) { + int64_t seconds_since_epoch = 0; + if (!internal::ParseTimestamp(data.c_str(), pattern_.c_str(), &seconds_since_epoch)) { return_error(context, data); return 0; } + // Drop any time component + seconds_since_epoch -= seconds_since_epoch % 86400; + *out_valid = true; - // ignore the time part - date::sys_seconds secs = date::sys_days(date::year(result.tm_year + 1900) / - (result.tm_mon + 1) / result.tm_mday); - int64_t seconds_since_epoch = secs.time_since_epoch().count(); - if (seconds_since_epoch == 0) { - return_error(context, data); - return 0; - } return seconds_since_epoch * 1000; } diff --git a/cpp/src/gandiva/to_date_holder.h b/cpp/src/gandiva/to_date_holder.h index 91133cc5269..c0c5afb8b31 100644 --- a/cpp/src/gandiva/to_date_holder.h +++ b/cpp/src/gandiva/to_date_holder.h @@ -27,11 +27,12 @@ #include "gandiva/execution_context.h" #include "gandiva/function_holder.h" #include "gandiva/node.h" +#include "gandiva/visibility.h" namespace gandiva { /// Function Holder for SQL 'to_date' -class ToDateHolder : public FunctionHolder { +class GANDIVA_EXPORT ToDateHolder : public FunctionHolder { public: ~ToDateHolder() override = default; diff --git a/cpp/src/gandiva/to_date_holder_test.cc b/cpp/src/gandiva/to_date_holder_test.cc index 2a207b2ad77..d5feea3ad88 100644 --- a/cpp/src/gandiva/to_date_holder_test.cc +++ b/cpp/src/gandiva/to_date_holder_test.cc @@ -18,6 +18,8 @@ #include #include +#include "arrow/test-util.h" + #include "gandiva/execution_context.h" #include "gandiva/to_date_holder.h" #include "precompiled/epoch_time_point.h" @@ -37,57 +39,60 @@ class TestToDateHolder : public ::testing::Test { return FunctionNode("to_date_utf8_utf8_int32", {field, pattern_node, suppres_error_node}, arrow::int64()); } + + protected: + ExecutionContext execution_context_; }; TEST_F(TestToDateHolder, TestSimpleDateTime) { std::shared_ptr to_date_holder; + ASSERT_OK(ToDateHolder::Make("YYYY-MM-DD HH:MI:SS", 1, &to_date_holder)); - auto status = ToDateHolder::Make("YYYY-MM-DD HH:MI:SS", 1, &to_date_holder); - EXPECT_EQ(status.ok(), true) << status.message(); - ExecutionContext execution_context; auto& to_date = *to_date_holder; bool out_valid; int64_t millis_since_epoch = - to_date(&execution_context, "1986-12-01 01:01:01", true, &out_valid); + to_date(&execution_context_, "1986-12-01 01:01:01", true, &out_valid); EXPECT_EQ(millis_since_epoch, 533779200000); millis_since_epoch = - to_date(&execution_context, "1986-12-01 01:01:01.11", true, &out_valid); + to_date(&execution_context_, "1986-12-01 01:01:01.11", true, &out_valid); EXPECT_EQ(millis_since_epoch, 533779200000); millis_since_epoch = - to_date(&execution_context, "1986-12-01 01:01:01 +0800", true, &out_valid); + to_date(&execution_context_, "1986-12-01 01:01:01 +0800", true, &out_valid); EXPECT_EQ(millis_since_epoch, 533779200000); millis_since_epoch = - to_date(&execution_context, "1986-12-11 01:30:00", true, &out_valid); + to_date(&execution_context_, "1986-12-11 01:30:00", true, &out_valid); EXPECT_EQ(millis_since_epoch, 534643200000); } TEST_F(TestToDateHolder, TestSimpleDate) { std::shared_ptr to_date_holder; + ASSERT_OK(ToDateHolder::Make("YYYY-MM-DD", 1, &to_date_holder)); - auto status = ToDateHolder::Make("YYYY-MM-DD", 1, &to_date_holder); - EXPECT_EQ(status.ok(), true) << status.message(); - ExecutionContext execution_context; auto& to_date = *to_date_holder; bool out_valid; int64_t millis_since_epoch = - to_date(&execution_context, "1986-12-01", true, &out_valid); + to_date(&execution_context_, "1986-12-01", true, &out_valid); EXPECT_EQ(millis_since_epoch, 533779200000); - millis_since_epoch = to_date(&execution_context, "1986-12-1", true, &out_valid); + millis_since_epoch = to_date(&execution_context_, "1986-12-1", true, &out_valid); EXPECT_EQ(millis_since_epoch, 533779200000); - millis_since_epoch = to_date(&execution_context, "1886-12-1", true, &out_valid); + millis_since_epoch = to_date(&execution_context_, "1886-12-1", true, &out_valid); EXPECT_EQ(millis_since_epoch, -2621894400000); - millis_since_epoch = to_date(&execution_context, "2012-12-1", true, &out_valid); + millis_since_epoch = to_date(&execution_context_, "2012-12-1", true, &out_valid); EXPECT_EQ(millis_since_epoch, 1354320000000); // wrong month. should return 0 since we are suppresing errors. millis_since_epoch = - to_date(&execution_context, "1986-21-01 01:01:01 +0800", true, &out_valid); + to_date(&execution_context_, "1986-21-01 01:01:01 +0800", true, &out_valid); + EXPECT_EQ(millis_since_epoch, 0); + + millis_since_epoch = + to_date(&execution_context_, "1986-01-40 01:01:01 +0800", true, &out_valid); EXPECT_EQ(millis_since_epoch, 0); } @@ -96,22 +101,22 @@ TEST_F(TestToDateHolder, TestSimpleDateTimeError) { auto status = ToDateHolder::Make("YYYY-MM-DD HH:MI:SS", 0, &to_date_holder); EXPECT_EQ(status.ok(), true) << status.message(); - ExecutionContext execution_context; auto& to_date = *to_date_holder; bool out_valid; int64_t millis_since_epoch = - to_date(&execution_context, "1986-21-01 01:01:01 +0800", true, &out_valid); + to_date(&execution_context_, "1986-01-40 01:01:01 +0800", true, &out_valid); + EXPECT_EQ(0, millis_since_epoch); std::string expected_error = - "Error parsing value 1986-21-01 01:01:01 +0800 for given format"; - EXPECT_TRUE(execution_context.get_error().find(expected_error) != std::string::npos) + "Error parsing value 1986-01-40 01:01:01 +0800 for given format"; + EXPECT_TRUE(execution_context_.get_error().find(expected_error) != std::string::npos) << status.message(); // not valid should not return error - execution_context.Reset(); - millis_since_epoch = to_date(&execution_context, "nullptr", false, &out_valid); + execution_context_.Reset(); + millis_since_epoch = to_date(&execution_context_, "nullptr", false, &out_valid); EXPECT_EQ(millis_since_epoch, 0); - EXPECT_TRUE(execution_context.has_error() == false); + EXPECT_TRUE(execution_context_.has_error() == false); } TEST_F(TestToDateHolder, TestSimpleDateTimeMakeError) { diff --git a/cpp/src/gandiva/tree_expr_builder.h b/cpp/src/gandiva/tree_expr_builder.h index cd261c8bf97..143febdb991 100644 --- a/cpp/src/gandiva/tree_expr_builder.h +++ b/cpp/src/gandiva/tree_expr_builder.h @@ -25,11 +25,12 @@ #include "gandiva/condition.h" #include "gandiva/expression.h" +#include "gandiva/visibility.h" namespace gandiva { /// \brief Tree Builder for a nested expression. -class TreeExprBuilder { +class GANDIVA_EXPORT TreeExprBuilder { public: /// \brief create a node on a literal. static NodePtr MakeLiteral(bool value); diff --git a/cpp/src/gandiva/value_validity_pair.h b/cpp/src/gandiva/value_validity_pair.h index 1bcd5d6a4bf..0de525d9704 100644 --- a/cpp/src/gandiva/value_validity_pair.h +++ b/cpp/src/gandiva/value_validity_pair.h @@ -21,11 +21,12 @@ #include #include "gandiva/gandiva_aliases.h" +#include "gandiva/visibility.h" namespace gandiva { /// Pair of vector/validities generated after decomposing an expression tree/subtree. -class ValueValidityPair { +class GANDIVA_EXPORT ValueValidityPair { public: ValueValidityPair(const DexVector& validity_exprs, DexPtr value_expr) : validity_exprs_(validity_exprs), value_expr_(value_expr) {} diff --git a/cpp/src/gandiva/visibility.h b/cpp/src/gandiva/visibility.h new file mode 100644 index 00000000000..450b3056b2e --- /dev/null +++ b/cpp/src/gandiva/visibility.h @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251) +#else +#pragma GCC diagnostic ignored "-Wattributes" +#endif + +#ifdef GANDIVA_STATIC +#define GANDIVA_EXPORT +#elif defined(GANDIVA_EXPORTING) +#define GANDIVA_EXPORT __declspec(dllexport) +#else +#define GANDIVA_EXPORT __declspec(dllimport) +#endif + +#define GANDIVA_NO_EXPORT +#else // Not Windows +#ifndef GANDIVA_EXPORT +#define GANDIVA_EXPORT __attribute__((visibility("default"))) +#endif +#ifndef GANDIVA_NO_EXPORT +#define GANDIVA_NO_EXPORT __attribute__((visibility("hidden"))) +#endif +#endif // Non-Windows + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif