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

stb_image_resize2.h does not compile due to: include file 'emmintrin.h' not found #1738

Open
sleeptightAnsiC opened this issue Jan 18, 2025 · 4 comments

Comments

@sleeptightAnsiC
Copy link

sleeptightAnsiC commented Jan 18, 2025

Hi,

[SEE MY COMMENT DOWN BELOW. Might not be an issue after all. Apologies]

This issue has been originally spotted in raylib discussion, here: raysan5/raylib#2994

Some compilers, such as TCC, are not able to compile stb_image_resize2.h due to its dependence on emmintrin.h Said header is compiler specific, so unlike MSVC / GCC / Clang, smaller compilers do not ship with it. Even in situation, where macros like __x86_64__ are predefined, it does not mean that emmintrin.h is available. There are of course more headers there that are not portable such as: immintrin.h, smmintrin.h or arm_neon.h

wasm_simd128.h should NOT be a problem since most compilers supporting wasm ship with it (though this may change). I'm not sure if there is any specification on those headers. I was not able to find any reference about detecting them.

I found a similar problem in different project - linux-test-project/ltp#980 - and they fixed it with the help of their build system (Autotools). Of course, I know this is not applicable to this project. In raylib we can easily make a workaround by doing #ifdef __TINYC__ since raylib claims only to support TCC, but I guess STB is expected to support more compilers.

To Reproduce

With TCC 0.9.28 (git trunk) or TCC 0.9.27 (latest release):

$ git clone https://github.com/nothings/stb.git
$ tcc stb/tests/test_c_compilation.c -I./stb
In file included from stb/tests/test_c_compilation.c:2:                                                                                                                                                    
./stb/stb_image_resize2.h:1279: error: include file 'emmintrin.h' not found 

with chibicc (git trunk):

$ git clone https://github.com/nothings/stb.git
$ chibicc stb/tests/test_c_compilation.c -I./stb
./stb/stb_image_resize2.h:1279:   #include <emmintrin.h>
                                           ^ emmintrin.h: cannot open file: No such file or directory

The code that checkes whether or not to include those headers is here:

stb/stb_image_resize2.h

Lines 384 to 422 in 5c20573

#ifdef _M_IX86_FP
#if ( _M_IX86_FP >= 1 )
#ifndef STBIR_SSE
#define STBIR_SSE
#endif
#endif
#endif
#if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE2__) || defined(STBIR_SSE) || defined(STBIR_SSE2)
#ifndef STBIR_SSE2
#define STBIR_SSE2
#endif
#if defined(__AVX__) || defined(STBIR_AVX2)
#ifndef STBIR_AVX
#ifndef STBIR_NO_AVX
#define STBIR_AVX
#endif
#endif
#endif
#if defined(__AVX2__) || defined(STBIR_AVX2)
#ifndef STBIR_NO_AVX2
#ifndef STBIR_AVX2
#define STBIR_AVX2
#endif
#if defined( _MSC_VER ) && !defined(__clang__)
#ifndef STBIR_FP16C // FP16C instructions are on all AVX2 cpus, so we can autoselect it here on microsoft - clang needs -m16c
#define STBIR_FP16C
#endif
#endif
#endif
#endif
#ifdef __F16C__
#ifndef STBIR_FP16C // turn on FP16C instructions if the define is set (for clang and gcc)
#define STBIR_FP16C
#endif
#endif
#endif

Let me know, if you need more info. I did not want to overbloat this ticket.

@sleeptightAnsiC sleeptightAnsiC changed the title stb_image_resize2.h does not compile on due to: include file 'emmintrin.h' not found stb_image_resize2.h does not compile due to: include file 'emmintrin.h' not found Jan 18, 2025
@sleeptightAnsiC
Copy link
Author

sleeptightAnsiC commented Jan 18, 2025

Ahhh, okey, my bad, there are STBIW_NO_SIMD and STBI_NO_SIMD so this is not really a problem.

~/stb $ echo "main(void) { return 0; }" > main.c
~/stb $ tcc tests/test_c_compilation.c main.c -I. -DSTBI_NO_SIMD -DSTBIW_NO_SIMD -lm

I've went too fast with reporting this. Apologies.
I will keep it open, because it's still a partially valid issue
but I'm fine with closing it.

sleeptightAnsiC added a commit to sleeptightAnsiC/raylib that referenced this issue Jan 19, 2025
…ot found

define STBIR_NO_SIMD when __TINYC__ is defined so stb_image_resize2 will
not include *mmintrin which are not supported by all compilers.

There are similar checks for __TINYC__ already elswere in raylib
and they are also mostly there to disable SIMD headers.

Additionally, move similar check for stb_image, to be a little bit
deeper. Before it was defining STBI_NO_SIMD without including stb_image
It was also clashing with note, causing said note to make no sense.

Fixes: raysan5#2994
Reference: nothings/stb#1738
raysan5 pushed a commit to raysan5/raylib that referenced this issue Jan 19, 2025
…ot found (#4707)

define STBIR_NO_SIMD when __TINYC__ is defined so stb_image_resize2 will
not include *mmintrin which are not supported by all compilers.

There are similar checks for __TINYC__ already elswere in raylib
and they are also mostly there to disable SIMD headers.

Additionally, move similar check for stb_image, to be a little bit
deeper. Before it was defining STBI_NO_SIMD without including stb_image
It was also clashing with note, causing said note to make no sense.

Fixes: #2994
Reference: nothings/stb#1738
ngynkvn pushed a commit to ngynkvn/raylib that referenced this issue Jan 21, 2025
…ot found (raysan5#4707)

define STBIR_NO_SIMD when __TINYC__ is defined so stb_image_resize2 will
not include *mmintrin which are not supported by all compilers.

There are similar checks for __TINYC__ already elswere in raylib
and they are also mostly there to disable SIMD headers.

Additionally, move similar check for stb_image, to be a little bit
deeper. Before it was defining STBI_NO_SIMD without including stb_image
It was also clashing with note, causing said note to make no sense.

Fixes: raysan5#2994
Reference: nothings/stb#1738
@jeffrbig2
Copy link

Yeah, use the NO_SIMD flags - I'd rather not block tiny completely, in case they add the simple instrincs we use in SSE2 mode.

@N-R-K
Copy link

N-R-K commented Jan 24, 2025

How about using __has_include to probe for the header?

#ifdef __has_include
  #if __has_include(<emmintrin.h>)
     // use <emmintrin.h>

Or use it to auto set the no-simd flag if you want to be more conservative?

#ifdef __has_include
  #if ! __has_include(<emmintrin.h>)
    #define STBI_NO_SIMD
  #endif
#endif

__has_include is supported by TCC and generally is pretty widely available AFAIK.

@sleeptightAnsiC
Copy link
Author

sleeptightAnsiC commented Jan 25, 2025

Thanks @N-R-K ,

It indeed works and fixes this issue for TCC. I wonder if there are any other smaller C compilers that support __has_include though? I don't really know any other than TCC. EDIT: Found one, cproc, so yes, it would also help with other compilers.

I've checked every possible code path and which headers are included with them, and wrote solution covering all of them [SEE BELOW]. Would you mind if I propose this as PR or is it still not preferable @jeffrbig2 @nothings ? I have noticed that there are some similar checks for GCC and MinGW that force STBI_NO_SIMD (e.g. in stb_image.h) so this wouldn't be anything new.

diff --git a/stb_image.h b/stb_image.h
index 9eedabe..fdde39c 100644
--- a/stb_image.h
+++ b/stb_image.h
@@ -695,6 +695,15 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
 #define STBI__X86_TARGET
 #endif
 
+
+#if defined(__has_include) && !defined(STBI_NO_SIMD)
+  #if (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !__has_include(<emmintrin.h>)
+    #define STBI_NO_SIMD
+  #elif defined(STBI_NEON) && !__has_include(<arm_neon.h>)
+    #define STBI_NO_SIMD
+  #endif
+#endif
+
 #if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
 // gcc doesn't support sse2 intrinsics unless you compile with -msse2,
 // which in turn means it gets to use SSE2 everywhere. This is unfortunate,
diff --git a/stb_image_resize2.h b/stb_image_resize2.h
index 2f26274..71e7f4e 100644
--- a/stb_image_resize2.h
+++ b/stb_image_resize2.h
@@ -1241,6 +1241,19 @@ static stbir__inline stbir_uint8 stbir__linear_to_srgb_uchar(float in)
 #define STBIR_NO_UNROLL_LOOP_START_INF_FOR STBIR_NO_UNROLL_LOOP_START
 #endif
 
+#if defined(__has_include) && !defined(STBIR_NO_SIMD)
+  #if defined(STBIR_SSE2) && (!__has_include(<emmintrin.h>) || !__has_include(<immintrin.h>))
+    #define STBIR_NO_SIMD
+  #elif defined(STBIR_AVX) && !__has_include(<smmintrin.h>)
+    #undef STBIR_AVX
+    #define STBIR_NO_AVX
+  #elif defined(STBIR_NEON) && !__has_include(<arm_neon.h>)
+    #define STBIR_NO_SIMD
+  #elif defined(STBIR_WASM) && !__has_include(<wasm_simd128.h>)
+    #define STBIR_NO_SIMD
+  #endif
+#endif
+
 #ifdef STBIR_NO_SIMD // force simd off for whatever reason
 
 // force simd off overrides everything else, so clear it all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants