瀏覽代碼

Add windows clang to CI (#5537)

- Add windows clang build step
- Closes https://github.com/assimp/assimp/issues/5519


Co-authored-by: Kim Kulling <[email protected]>
Co-authored-by: Kim Kulling <[email protected]>
Kim Kulling 1 周之前
父節點
當前提交
a79dc358cf

+ 7 - 3
.github/workflows/ccpp.yml

@@ -16,9 +16,13 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++]
+        name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, windows-latest-clang.exe, ubuntu-latest-clang++]
         # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
         include:
+          - name: windows-latest-clang.exe
+            os: windows-latest
+            cxx: clang++.exe
+            cc: clang.exe
           - name: windows-latest-cl.exe
             os: windows-latest
             cxx: cl.exe
@@ -69,13 +73,13 @@ jobs:
           ${{ runner.os }}-DX_SDK
 
     - name: Download DXSetup
-      if: contains(matrix.name, 'windows') && steps.dxcache.outputs.cache-hit != 'true'
+      if: contains(matrix.name, 'windows-latest-cl.exe') && steps.dxcache.outputs.cache-hit != 'true'
       run: |
         curl -s -o DXSDK_Jun10.exe --location https://download.microsoft.com/download/A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe
         cmd.exe /c start /wait .\DXSDK_Jun10.exe /U /O /F /S /P "${{ github.workspace }}\DX_SDK"
 
     - name: Set Windows specific CMake arguments
-      if: contains(matrix.name, 'windows')
+      if: contains(matrix.name, 'windows-latest-cl.exe')
       id: windows_extra_cmake_args
       run: echo ":set-output name=args::=-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1" >> $GITHUB_OUTPUT
     

+ 14 - 4
CMakeLists.txt

@@ -309,6 +309,17 @@ IF( UNIX )
   ENDIF()
 ENDIF()
 
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND WIN32)
+  ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+  ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+ENDIF()
+
+IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
+  ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+  ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+endif ()
+
+
 # Grouped compiler settings ########################################
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
   IF(NOT ASSIMP_HUNTER_ENABLED)
@@ -354,14 +365,13 @@ ELSEIF(MSVC)
   if(NOT /utf-8 IN_LIST CMAKE_CXX_FLAGS)
     # Source code is encoded in UTF-8
     ADD_COMPILE_OPTIONS(/source-charset:utf-8)
-  endif ()
-
+  endif()
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
-  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
-  SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+  SET(CMAKE_CXX_FLAGS "-Wno-deprecated-non-prototype -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
+  SET(CMAKE_C_FLAGS "-Wno-deprecated-non-prototype -fno-strict-aliasing ${CMAKE_C_FLAGS}")
 ELSEIF( MINGW )
   IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
     message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")

+ 0 - 6
code/CMakeLists.txt

@@ -1318,11 +1318,6 @@ if(MSVC10)
   endif()
 endif()
 
-IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
-  ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
-  ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-endif ()
-
 IF(NOT ASSIMP_HUNTER_ENABLED)
   if (UNZIP_FOUND)
     SET (unzip_compile_SRCS "")
@@ -1415,7 +1410,6 @@ add_compile_options(
 IF (ASSIMP_WARNINGS_AS_ERRORS)
   MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
   IF (MSVC)
-
     IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
       TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
         -Wno-microsoft-enum-value

+ 9 - 0
contrib/zlib/gzguts.h

@@ -12,6 +12,15 @@
 #  endif
 #endif
 
+#ifdef _WIN32
+#  ifndef _CRT_SECURE_NO_WARNINGS
+#    define _CRT_SECURE_NO_WARNINGS
+#  endif // _CRT_SECURE_NO_WARNINGS
+#  ifndef _CRT_NONSTDC_NO_DEPRECATE
+#    define _CRT_NONSTDC_NO_DEPRECATE
+#  endif // _CRT_NONSTDC_NO_DEPRECATE
+#endif // _WIN32
+
 #ifdef HAVE_HIDDEN
 #  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
 #else

+ 9 - 0
contrib/zlib/gzlib.c

@@ -3,6 +3,15 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
+#ifdef _WIN32
+#  ifndef _CRT_NONSTDC_NO_DEPRECATE
+#    define _CRT_NONSTDC_NO_DEPRECATE
+#  endif 
+#  ifndef _CRT_SECURE_NO_WARNINGS
+#    define _CRT_SECURE_NO_WARNINGS
+#  endif //_CRT_SECURE_NO_WARNINGS
+#endif // _WIN32
+
 #include "gzguts.h"
 
 #if defined(_WIN32) && !defined(__BORLANDC__)

+ 9 - 0
contrib/zlib/gzread.c

@@ -3,6 +3,15 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
+#ifdef _WIN32
+#  ifndef _CRT_SECURE_NO_WARNINGS
+#    define _CRT_SECURE_NO_WARNINGS
+#  endif // _CRT_SECURE_NO_WARNINGS
+#  ifndef _CRT_NONSTDC_NO_DEPRECATE
+#    define _CRT_NONSTDC_NO_DEPRECATE
+#  endif // _CRT_NONSTDC_NO_DEPRECATE
+#endif // _WIN32
+
 #include "gzguts.h"
 
 /* Local functions */

+ 0 - 1
contrib/zlib/gzwrite.c

@@ -2,7 +2,6 @@
  * Copyright (C) 2004-2019 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
-
 #include "gzguts.h"
 
 /* Local functions */

+ 0 - 1
contrib/zlib/zutil.c

@@ -23,7 +23,6 @@ z_const char * const z_errmsg[10] = {
     (z_const char *)""
 };
 
-
 const char * ZEXPORT zlibVersion()
 {
     return ZLIB_VERSION;

+ 1 - 1
include/assimp/types.h

@@ -118,7 +118,7 @@ extern "C" {
 
 /** Maximum dimension for strings, ASSIMP strings are zero terminated. */
 #ifdef __cplusplus
-static const size_t AI_MAXLEN = 1024;
+static constexpr size_t AI_MAXLEN = 1024;
 #else
 #define AI_MAXLEN 1024
 #endif

+ 8 - 2
test/CMakeLists.txt

@@ -59,6 +59,10 @@ endif()
 # Assimp library can be found, even if it is not installed system-wide yet.
 LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
 
+SET(TOOLS
+    unit/Tools/TestTools.h
+)
+
 SET( COMMON
   unit/utSimd.cpp
   unit/utIOSystem.cpp
@@ -219,6 +223,7 @@ SOURCE_GROUP( UnitTests\\GeometryTools FILES ${Geometry} )
 SOURCE_GROUP( UnitTests\\ImportExport  FILES ${IMPORTERS} )
 SOURCE_GROUP( UnitTests\\Material      FILES ${MATERIAL} )
 SOURCE_GROUP( UnitTests\\Math          FILES ${MATH} )
+SOURCE_GROUP( UnitTests\\Tools         FILES ${TOOLS} )
 SOURCE_GROUP( UnitTests\\PostProcess   FILES ${POST_PROCESSES})
 
 add_executable( unit
@@ -227,11 +232,12 @@ add_executable( unit
     ../code/Common/Version.cpp
 	../code/Common/Base64.cpp
 	${COMMON}
-  ${Geometry}
+    ${Geometry}
 	${IMPORTERS}
 	${MATERIAL}
 	${MATH}
-  ${POST_PROCESSES}
+    ${POST_PROCESSES}
+    ${TOOLS}
 )
 
 if(ASSIMP_HUNTER_ENABLED)

+ 5 - 16
test/unit/TestIOStream.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2025, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,20 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace ::Assimp;
 
-class TestDefaultIOStream : public DefaultIOStream {
+class TestDefaultIOStream final : public DefaultIOStream {
 public:
-    TestDefaultIOStream()
-        : DefaultIOStream() {
-        // empty
-    }
-
-    TestDefaultIOStream( FILE* pFile, const std::string &strFilename )
-    : DefaultIOStream( pFile, strFilename ) {
-        // empty
-    }
-
-    virtual ~TestDefaultIOStream() {
-        // empty
-    }
+    TestDefaultIOStream() = default;
+    TestDefaultIOStream(FILE* pFile, const std::string &strFilename) : DefaultIOStream(pFile, strFilename) {}
+    ~TestDefaultIOStream() override = default;
 };
-

+ 27 - 0
test/unit/Tools/TestTools.h

@@ -0,0 +1,27 @@
+#pragma once
+
+#include <gtest/gtest.h>
+#include <cstdio>
+#include <string>
+
+namespace Assimp::Unittest {
+
+    class TestTools final {
+    public:
+        TestTools() = default;
+        ~TestTools() = default;
+        static bool openFilestream(FILE **pFile, const char *filename, const char *mode);
+    };
+
+    inline bool TestTools::openFilestream(FILE **fs, const char *filename, const char *mode) {
+#if defined(_WIN32)
+        errno_t err{ 0 };
+        err = fopen_s(fs, filename, mode);
+        EXPECT_EQ(err, 0);
+#else
+        *fs = fopen(filename, mode);
+#endif
+        return fs != nullptr;
+    }
+
+} // namespace Assimp::Unittest

+ 31 - 13
test/unit/UnitTestFileGenerator.h

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -39,42 +39,60 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
 #pragma once
+#ifdef _WIN32
+#  ifndef _CRT_NONSTDC_NO_DEPRECATE
+#    define _CRT_NONSTDC_NO_DEPRECATE
+#  endif // _CRT_NONSTDC_NO_DEPRECATE
+#  ifndef _CRT_SECURE_NO_WARNINGS
+#     define _CRT_SECURE_NO_WARNINGS
+#  endif
+#endif
 
 #include <cstdio>
 #include <cstdlib>
 #include <gtest/gtest.h>
 
 #if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
-#define TMP_PATH "./"
+#   define TMP_PATH "./"
 #elif defined(__GNUC__) || defined(__clang__)
-#define TMP_PATH "/tmp/"
+#   define TMP_PATH "/var/tmp/"
 #endif
 
 #if defined(_MSC_VER)
+
 #include <io.h>
-inline FILE* MakeTmpFile(char* tmplate)
-{
-    auto pathtemplate = _mktemp(tmplate);
+inline FILE* MakeTmpFile(char* tmplate, size_t len, std::string &tmpName) {
+    size_t tmpLen = len + 1;
+    char *pathtemplate = new char[tmpLen];
+    strcpy_s(pathtemplate, tmpLen, tmplate);
+    int err_code = _mktemp_s(pathtemplate, tmpLen);
+    EXPECT_EQ(err_code, 0);
     EXPECT_NE(pathtemplate, nullptr);
-    if(pathtemplate == nullptr)
-    {
+    if(pathtemplate == nullptr) {
+        delete[] pathtemplate;
         return nullptr;
     }
-    auto* fs = std::fopen(pathtemplate, "w+");
+    errno_t err;
+    FILE *fs{nullptr};
+    err = fopen_s(&fs, pathtemplate, "w+");
+    EXPECT_EQ(0, err);
+    tmpName = pathtemplate;
     EXPECT_NE(fs, nullptr);
+    delete[] pathtemplate;
+
     return fs;
 }
 #elif defined(__GNUC__) || defined(__clang__)
-inline FILE* MakeTmpFile(char* tmplate)
-{
+inline FILE *MakeTmpFile(char *tmplate, size_t len, std::string &tmpName) {
     auto fd = mkstemp(tmplate);
     EXPECT_NE(-1, fd);
-    if(fd == -1)
-    {
+    if(fd == -1) {
         return nullptr;
     }
     auto fs = fdopen(fd, "w+");
     EXPECT_NE(nullptr, fs);
+    tmpName += tmplate;
+
     return fs;
 }
 #endif

+ 0 - 2
test/unit/utBlenderImportExport.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2025, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 0 - 2
test/unit/utBlenderIntermediate.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2025, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 7 - 5
test/unit/utDefaultIOStream.cpp

@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <gtest/gtest.h>
 #include "TestIOStream.h"
 #include "UnitTestFileGenerator.h"
+#include "Tools/TestTools.h"
 #include <cstdio>
 #include <cstdlib>
 #include <string>
@@ -60,8 +61,9 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
     const auto dataSize = sizeof(data);
     const auto dataCount = dataSize / sizeof(*data);
 
-    char fpath[] = { TMP_PATH"rndfp.XXXXXX" };
-    auto* fs = MakeTmpFile(fpath);
+    char fpath[] = { TMP_PATH"rndfp.XXXXXX\0" };
+    std::string tmpName;
+    auto *fs = MakeTmpFile(fpath, std::strlen(fpath), tmpName);
     ASSERT_NE(nullptr, fs);
     {
         auto written = std::fwrite(data, sizeof(*data), dataCount, fs );
@@ -71,13 +73,13 @@ TEST_F( utDefaultIOStream, FileSizeTest ) {
         ASSERT_EQ(vflush, 0);
 
 		std::fclose(fs);
-		fs = std::fopen(fpath, "r");
 
-		ASSERT_NE(nullptr, fs);
+        EXPECT_TRUE(Unittest::TestTools::openFilestream(&fs, tmpName.c_str(), "r"));
+        ASSERT_NE(nullptr, fs);
 
         TestDefaultIOStream myStream( fs, fpath);
         size_t size = myStream.FileSize();
         EXPECT_EQ( size, dataSize);
     }
-    remove(fpath);
+    remove(tmpName.c_str());
 }

+ 23 - 18
test/unit/utIOStreamBuffer.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2025, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -44,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "UnitTestPCH.h"
 #include <assimp/IOStreamBuffer.h>
 #include "TestIOStream.h"
+#include "Tools/TestTools.h"
 #include "UnitTestFileGenerator.h"
 
 class IOStreamBufferTest : public ::testing::Test {
@@ -86,18 +85,21 @@ TEST_F( IOStreamBufferTest, open_close_Test ) {
     const auto dataCount = dataSize / sizeof(*data);
 
     char fname[]={ "octest.XXXXXX" };
-    auto* fs = MakeTmpFile(fname);
+    std::string tmpName;
+    auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
     ASSERT_NE(nullptr, fs);
 
-    auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
+    auto written = std::fwrite(data, sizeof(*data), dataCount, fs);
     EXPECT_NE( 0U, written );
     auto flushResult = std::fflush( fs );
 	ASSERT_EQ(0, flushResult);
-	std::fclose( fs );
-	fs = std::fopen(fname, "r");
-	ASSERT_NE(nullptr, fs);
+	fclose(fs);
+
+    FILE *new_fs{ nullptr };
+    EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
+    ASSERT_NE(nullptr, new_fs);
     {
-        TestDefaultIOStream myStream( fs, fname );
+        TestDefaultIOStream myStream(new_fs, fname);
 
         EXPECT_TRUE( myBuffer.open( &myStream ) );
         EXPECT_FALSE( myBuffer.open( &myStream ) );
@@ -111,8 +113,9 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
     const auto dataSize = sizeof(data);
     const auto dataCount = dataSize / sizeof(*data);
 
-    char fname[]={ "readlinetest.XXXXXX" };
-    auto* fs = MakeTmpFile(fname);
+    char fname[]={ "readlinetest.XXXXXX\0" };
+    std::string tmpName;
+    auto* fs = MakeTmpFile(fname, std::strlen(fname), tmpName);
     ASSERT_NE(nullptr, fs);
 
     auto written = std::fwrite( data, sizeof(*data), dataCount, fs );
@@ -121,23 +124,25 @@ TEST_F( IOStreamBufferTest, readlineTest ) {
 	auto flushResult = std::fflush(fs);
 	ASSERT_EQ(0, flushResult);
 	std::fclose(fs);
-	fs = std::fopen(fname, "r");
-	ASSERT_NE(nullptr, fs);
+
+    FILE *new_fs{ nullptr };
+    EXPECT_TRUE(Unittest::TestTools::openFilestream(&new_fs, tmpName.c_str(), "r"));
+    ASSERT_NE(nullptr, new_fs);
 
     const auto tCacheSize = 26u;
 
-    IOStreamBuffer<char> myBuffer( tCacheSize );
-    EXPECT_EQ(tCacheSize, myBuffer.cacheSize() );
+    IOStreamBuffer<char> myBuffer(tCacheSize);
+    EXPECT_EQ(tCacheSize, myBuffer.cacheSize());
 
-    TestDefaultIOStream myStream( fs, fname );
+    TestDefaultIOStream myStream(new_fs, fname);
     auto size = myStream.FileSize();
     auto numBlocks = size / myBuffer.cacheSize();
     if ( size % myBuffer.cacheSize() > 0 ) {
         numBlocks++;
     }
-    EXPECT_TRUE( myBuffer.open( &myStream ) );
-    EXPECT_EQ( numBlocks, myBuffer.getNumBlocks() );
-    EXPECT_TRUE( myBuffer.close() );
+    EXPECT_TRUE(myBuffer.open(&myStream));
+    EXPECT_EQ(numBlocks, myBuffer.getNumBlocks() );
+    EXPECT_TRUE(myBuffer.close() );
 }
 
 TEST_F( IOStreamBufferTest, accessBlockIndexTest ) {

+ 3 - 2
test/unit/utglTF2ImportExport.cpp

@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #include "AbstractImportExportBase.h"
 #include "UnitTestPCH.h"
-
+#include "Tools/TestTools.h"
 #include <assimp/commonMetaData.h>
 #include <assimp/postprocess.h>
 #include <assimp/config.h>
@@ -472,7 +472,8 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
 std::vector<char> ReadFile(const char *name) {
     std::vector<char> ret;
 
-    FILE *p = ::fopen(name, "r");
+    FILE *p{ nullptr };
+    EXPECT_TRUE(Unittest::TestTools::openFilestream(&p, name, "r"));
     if (nullptr == p) {
         return ret;
     }