nelua-lang icon indicating copy to clipboard operation
nelua-lang copied to clipboard

Error when cross compiling using zig cc

Open alliby opened this issue 10 months ago • 28 comments
trafficstars

i tried to cross compile nelua code from my linux machine to windows using zig cc and mingw using both these commands

nelua test.nelua --cc="zig cc -target x86-windows"
nelua test.nelua --cc="x86_64-w64-mingw32-gcc"

for this code:

## pragma{nogc=true}
##[[
-- Compile GLAD
--------------------------------------------------
cinclude "glad/glad.h"
cfile "glad/src/glad.c"
cincdir "glad/include"

-- generate bindings for glad
local nldecl = require 'nelua.plugins.nldecl'
if not fs.isfile('glad/init.nelua') then
   nldecl.generate_bindings_file{
      include_dirs = { 'glad/include' },
      output_file = 'glad/init.nelua',
      parse_includes = {'glad/glad.h'},
   }
end
--------------------------------------------------
]]

-- Include GLAD
require "glad"

give the same error for the generated glad bindings:

test.nelua:1:1: from: AST node Block
## pragma{nogc=true}
^~~~~~~~~~~~~~~~~~~~
init.nelua:1:1: from: AST node Block
global gladGLversionStruct: type <cimport,nodecl,ctypedef'gladGLversionStruct'> = @record{
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
init.nelua:7541:8: error: in variable 'INT_FAST16_MAX' declaration: constant value `9223372036854775807` for type `clong` is out of range, the minimum is `-2147483648` and maximum is `2147483647`
global INT_FAST16_MAX: clong <comptime> = 9223372036854775807
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

a workaround for this is manually compiling the generated c code from nelua using the appropriate c compiler

nelua version:

  λ ~ nelua -v
Nelua 0.2.0-dev
Build number: 1629
Git date: 2024-12-14 11:06:09 -0300
Git hash: a69a12d1e1e5ee0bfab299350e5d707ff7b2e744
Semantic version: 0.2.0-dev.1629+a69a12d1
Copyright (C) 2019-2025 Eduardo Bart (https://nelua.io/)

my environment

OS: Void x86_64
Kernel: Linux 6.12.6_3
CPU: 12th Gen Intel(R) Core(TM) i5-1245U (12) @ 4.40 GHz

alliby avatar Jan 10 '25 00:01 alliby

~~Your pragma syntax is wrong; here's the correct one: ## pragmas.nogc = true~~

Actually, I have navigated in Nelua's internals some external libraries and have found this syntax. I have never seen this kind of syntax before.

stefanos82 avatar Jan 10 '25 09:01 stefanos82

I think it's your bindings fault, it uses clong instead of clonglong which obviously has fewer limits than clonglong.

0komo avatar Jan 13 '25 22:01 0komo

Also, zig cc will still works as a C compiler for Nelua.

komo @ /tmp
 └─╴🞂 nixs nixpkgs/nixos-unstable#{zig_0_13,nelua}
source: Error encountered while sourcing file '/nix/store/nwpfzclhxd3fnmszd173fjj2ngpba1gi-source/dotfiles/etc/lscolors.fish':
source: No such file or directory
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish

󱄅 komo @ /tmp
 └─╴🞂 nelua -v
Nelua 0.2.0-dev
Build number: 0
Git date: 2024-12-14
Git hash: a69a12d1e1e5ee0bfab299350e5d707ff7b2e744
Semantic version: 0.2.0-dev.0+a69a12d1
Copyright (C) 2019-2025 Eduardo Bart (https://nelua.io/)

󱄅 komo @ /tmp
 └─╴🞂 zig version
0.13.0

󱄅 komo @ /tmp
 └─╴🞂 nelua -V -i "local a = 9223372036854775807; print(a)" --cc "zig cc"
generated /home/komo/.cache/nelua/eval_EePzfW6tFYR.c
zig cc -x c "/home/komo/.cache/nelua/eval_EePzfW6tFYR.c" -x none -Wno-unused-command-line-argument -fwrapv -fno-strict-aliasing -g -o "/home/komo/.cache/nelua/eval_EePzfW6tFYR"
/home/komo/.cache/nelua/eval_EePzfW6tFYR
9223372036854775807

0komo avatar Jan 13 '25 22:01 0komo

I think it's your bindings fault, it uses clong instead of clonglong which obviously has fewer limits than clonglong.

Now that you have mentioned it, I've just noticed this nelua test.nelua --cc="zig cc -target x86-windows".

Can we presume it generated a 32-bit C version behind the scenes this way?

To verify it we can run it with --print-code flag:

nelua test.nelua --cc="zig cc -target x86-windows" --print-code

stefanos82 avatar Jan 13 '25 22:01 stefanos82

With Nelua command: nelua -i "local a = 9223372036854775807; print(a)" --cc "zig cc -target x86-windows" --print-code

The result
/* ------------------------------ DIRECTIVES -------------------------------- */
/* Disable some warnings that the generated code can trigger. */
#if defined(__clang__) && __clang_major__ >= 3
  #pragma clang diagnostic ignored "-Wtype-limits"
  #pragma clang diagnostic ignored "-Wwrite-strings"
  #pragma clang diagnostic ignored "-Wunused"
  #pragma clang diagnostic ignored "-Wunused-parameter"
  #pragma clang diagnostic ignored "-Wmissing-field-initializers"
  #pragma clang diagnostic ignored "-Wparentheses-equality"
  #pragma clang diagnostic ignored "-Wtautological-compare"
  #pragma clang diagnostic ignored "-Wmissing-braces"
  #ifndef __cplusplus
    #pragma clang diagnostic ignored "-Wincompatible-pointer-types"
    #pragma clang diagnostic error   "-Wimplicit-function-declaration"
    #pragma clang diagnostic error   "-Wimplicit-int"
  #else
    #pragma clang diagnostic ignored "-Wnarrowing"
    #pragma clang diagnostic ignored "-Wc99-designator"
  #endif
#elif defined(__GNUC__) && __GNUC__ >= 5
  #pragma GCC diagnostic ignored "-Wtype-limits"
  #pragma GCC diagnostic ignored "-Wwrite-strings"
  #pragma GCC diagnostic ignored "-Wunused-parameter"
  #pragma GCC diagnostic ignored "-Wunused-value"
  #pragma GCC diagnostic ignored "-Wunused-variable"
  #pragma GCC diagnostic ignored "-Wunused-function"
  #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
  #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
  #ifndef __cplusplus
    #pragma GCC diagnostic ignored "-Wmissing-braces"
    #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
    #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
    #pragma GCC diagnostic error   "-Wimplicit-int"
  #else
    #pragma GCC diagnostic ignored "-Wnarrowing"
  #endif
#endif
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
  #define _CRT_SECURE_NO_WARNINGS
#endif
/* Macro used to perform compile-time checks. */
#if __STDC_VERSION__ >= 201112L
  #define NELUA_STATIC_ASSERT _Static_assert
#elif __cplusplus >= 201103L
  #define NELUA_STATIC_ASSERT static_assert
#else
  #define NELUA_STATIC_ASSERT(x, y)
#endif
/* Macro used to get alignment of a type. */
#if __STDC_VERSION__ >= 201112L
  #define NELUA_ALIGNOF _Alignof
#elif __cplusplus >= 201103L
  #define NELUA_ALIGNOF alignof
#elif defined(__GNUC__)
  #define NELUA_ALIGNOF __alignof__
#elif defined(_MSC_VER)
  #define NELUA_ALIGNOF __alignof
#else
  #define NELUA_ALIGNOF(x)
#endif
/* Checks if Nelua and C agrees on pointer size. */
NELUA_STATIC_ASSERT(sizeof(void*) == 4 && NELUA_ALIGNOF(void*) == 4, "Nelua and C disagree on pointer size or alignment");
/* Enable 64 bit offsets for stdio APIs. */
#if !defined(_FILE_OFFSET_BITS) && __SIZEOF_LONG__ >= 8
  #define _FILE_OFFSET_BITS 64
#endif
/* Enable POSIX APIs in included headers. */
#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) && !defined(_DEFAULT_SOURCE)
  #if defined(__gnu_linux__)
    #define _GNU_SOURCE
  #else
    #define _XOPEN_SOURCE 600
  #endif
#endif
#include <stdint.h>
#include <stdio.h>
/* ------------------------------ DECLARATIONS ------------------------------ */
static int64_t eval_EePzfW6tFYR_a = 9223372036854775807LL;
static void nelua_print_1(int64_t a1);
static int nelua_main(int argc, char** argv);
/* ------------------------------ DEFINITIONS ------------------------------- */
void nelua_print_1(int64_t a1) {
  fprintf(stdout, "%lli", (long long)a1);
  fputs("\n", stdout);
  fflush(stdout);
}
int nelua_main(int argc, char** argv) {
  nelua_print_1(eval_EePzfW6tFYR_a);
  return 0;
}
int main(int argc, char** argv) {
  return nelua_main(argc, argv);
}

Note: Zig CC is basically just an LLVM Clang frontend embedded into Zig toolchain.

0komo avatar Jan 13 '25 22:01 0komo

Another interesting thing is that the target is listed in Zig documentation as x86-windows-gnu, not as x86-windows; do you think it matters?

stefanos82 avatar Jan 13 '25 23:01 stefanos82

Another interesting thing is that the target is listed in Zig documentation as x86-windows-gnu, not as x86-windows; do you think it matters?

gnu is just an ABI in the Zig triple target, so it isn't really matter.

0komo avatar Jan 14 '25 04:01 0komo

the weirdest thing is how its still working on linux with no error using the same bindings

alliby avatar Jan 14 '25 16:01 alliby

For example:

  • This works:

    nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" 
    
  • This does not work:

    nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86-windows"
    

alliby avatar Jan 14 '25 16:01 alliby

* This works:
  ```
  nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" 
  ```

* This does not work:
  ```
  nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86-windows"
  ```

Interesting...can you try

nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86_64-windows"

stefanos82 avatar Jan 14 '25 17:01 stefanos82

the same error

  λ ~ nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86_64-windows"
eval_HzkndbMsuES:1:1: from: AST node Block
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval_HzkndbMsuES:1:7: error: in variable 'INT_FAST16_MAX' declaration: constant value `9223372036854775807` for type `clong` is out of range, the minimum is `-2147483648` and maximum is `2147483647`
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

alliby avatar Jan 14 '25 17:01 alliby

Seems like it throws an error as expected: On a 32-bit computer, clong is of size 32-bit signed, thus the error

out of range, the minimum is `-2147483648` and maximum is `2147483647`

You are trying to assign it with a number larger than the variable type's size.

To verify what I am saying, can you try:

nelua -i "local INT_FAST16_MAX: culong <comptime> = (@culong)(-1); print(INT_FAST16_MAX)" --cc="zig cc -target x86-windows"

stefanos82 avatar Jan 14 '25 21:01 stefanos82

Wow,that compile fine

alliby avatar Jan 14 '25 21:01 alliby

what output did it return?

stefanos82 avatar Jan 14 '25 22:01 stefanos82

using wine it return

4294967295

alliby avatar Jan 14 '25 22:01 alliby

Very nice; it's exactly as I have suspected. You were hard coding a number larger than your 32-bit version could handle.

stefanos82 avatar Jan 14 '25 22:01 stefanos82

yeah, but still does not compile for windows 64-bit while working fine for 64-bit linux

alliby avatar Jan 14 '25 22:01 alliby

What is the error message it throws?

stefanos82 avatar Jan 14 '25 22:01 stefanos82

so i'm confused about the default behavior of the compiler, does it allow overflow at compile time or not

alliby avatar Jan 14 '25 22:01 alliby

You mean nelua compiler or zig cc?

stefanos82 avatar Jan 14 '25 22:01 stefanos82

the same error

  λ ~ nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86_64-windows"
eval_HzkndbMsuES:1:1: from: AST node Block
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval_HzkndbMsuES:1:7: error: in variable 'INT_FAST16_MAX' declaration: constant value `9223372036854775807` for type `clong` is out of range, the minimum is `-2147483648` and maximum is `2147483647`
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

the same as i mentioned earlier

alliby avatar Jan 14 '25 22:01 alliby

the nelua compiler, C compilers allow that

alliby avatar Jan 14 '25 22:01 alliby

I think you are tired, because what you are doing is rather funny.

You are HARDCODING a huge number of signed 64-bit, this part here local INT_FAST16_MAX: clong <comptime> = 9223372036854775807 and you expect it to run on 32-bit!

Obviously, as we both know 2 ^ 32 - 1 is 4294967295 for unsigned 32-bit integer, but if we are using a signed integer (the case of clong that fallbacks to 31-bit signed integer), then we get -2147483648 as minimum and 2147483647 as maximum.

Do you understand now where's the issue?

stefanos82 avatar Jan 14 '25 22:01 stefanos82

Yes i understand the issue correctly. you can try to assign this big number to an integer in C and it would compile with some overflow warnings, even for 32-bit version. But that not the main problem here. i'm just using the bindings for glad using the nldecl plugin, i'm not HARDCODING it. and it compiles for x86_64-linux and not for x86_64-windows which is weird.

alliby avatar Jan 14 '25 22:01 alliby

About hardcoding, I was referring at this code:

  λ ~ nelua -i "local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)" --cc="zig cc -target x86_64-windows"
eval_HzkndbMsuES:1:1: from: AST node Block
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval_HzkndbMsuES:1:7: error: in variable 'INT_FAST16_MAX' declaration: constant value `9223372036854775807` for type `clong` is out of range, the minimum is `-2147483648` and maximum is `2147483647`
local INT_FAST16_MAX: clong <comptime> = 9223372036854775807; print(INT_FAST16_MAX)
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here it's hardcoded, obviously.

About the x86_84-windows target issue, I guess it's a Zig issue?

stefanos82 avatar Jan 14 '25 22:01 stefanos82

seriously. if you read the issue description i mention that the generated c code compiles fine with ZIg.

alliby avatar Jan 14 '25 22:01 alliby

and it compiles for x86_64-linux and not for x86_64-windows which is weird.

I thought it was Zig's responsibility to emit a 64-bit windows version target output, which fails for some reason as you say, so...excuse my confusion!

stefanos82 avatar Jan 14 '25 22:01 stefanos82

I'll need to look more in depth later, but I believe nelua is being misinformed by the compiler (in this situation of cross-compiling, since zig cc alone seems to work fine from what I read here).

When compiling, Nelua will invoke the C compiler (like gcc, zig cc, etc) and get all the information about the C environment (like the size of types), see get_cc_info:

https://github.com/edubart/nelua-lang/blob/a69a12d1e1e5ee0bfab299350e5d707ff7b2e744/lualib/nelua/ccompiler.lua#L202

I believe the compiler is not giving the right information to Nelua.

About working on Linux but not on Windows in this case:

Reading here on Cpp Reference (which also covers standard C), it's shown that long has different sizes between Windows and Unix:

Type specifier C standard LP32 ILP32 LLP64 LP64
long at least 32 32 32 32 64

[!NOTE] On the same page, on "Data models", it says that on 64-bit systems, Win64 API uses LLP64 while Unix uses LP64, where long is 4 bytes and 8 bytes respectively.

Source: https://en.cppreference.com/w/c/language/arithmetic_types

TL;DR: I believe the cross-compilation to Windows on Zig CC is messing up the ccinfo data that Nelua uses.

Andre-LA avatar Jan 14 '25 22:01 Andre-LA

Seems to be fixed with latest Zig. Can't reproduce on Gentoo Linux (host toolchain: x86_64-pc-linux-musl).

~ $ zig version
0.15.0-dev.919+044ccf413
~ $ nelua -v
Nelua 0.2.0-dev
Build number: 1635
Git date: 2025-06-24 16:22:08 -0300
Git hash: a58450563e2d2ec49bff499865c8b5cfdf6ff81a
Semantic version: 0.2.0-dev.1635+a5845056
Copyright (C) 2019-2025 Eduardo Bart (https://nelua.io/)

Steps to reproduce:

  • git clone https://github.com/nitrix/glad.git
  • nelua test.nelua --cc="zig cc -target x86-windows"
~/.cache/nelua $ file test.exe
test.exe: PE32 executable for MS Windows 6.00 (console), Intel i386, 7 sections
~/.cache/nelua $ ./test.exe
bash: ./test.exe: cannot execute binary file: Exec format error

LinuxUserGD avatar Jul 12 '25 15:07 LinuxUserGD