What are the differences bwteen clang/clang++ and "zig cc/c++"?

I have built the skia lib successfully with clang with the following config (although there are some AVX warnings).

bin/gn gen out/Static-m138 --args='
    is_official_build=true
    skia_enable_gpu=true
    skia_use_system_expat=false
    skia_use_system_freetype2=false
    skia_use_system_harfbuzz=false
    skia_use_system_icu=false
    skia_use_system_libjpeg_turbo=false
    skia_use_system_libpng=false
    skia_use_system_libwebp=false
    skia_use_system_zlib=false
    cc="clang"
    cxx="clang++"
    '

However, when I replace the compilers with

    cc="zig cc"
    cxx="zig c++"

The build fails with many AVX errors:

...
../../modules/skcms/src/Transform_inl.h:884:9: error: AVX vector return of type 'float __attribute__((ext_vector_type(16)))' (vector of 16 'float' values) without 'evex512' enabled changes the ABI
  884 |     b = cast<F>(load_3<U32>(rgb+2) ) * (1/255.0f);
      |         ^
../../modules/skcms/src/Transform_inl.h:889:16: error: AVX vector return of type 'unsigned int __attribute__((ext_vector_type(16)))' (vector of 16 'unsigned int' values) without 'evex512' enabled changes the ABI
  889 |     U32 rgba = load<U32>(src + 4*i);
      |                ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

What extra options do I need to make the build with zig compiler succeed?

zig cc/c++ will add ‘opinionated’ command line options to the clang frontend invocation which clang/clang++ doesn’t enable by default, e.g. one notable difference is that zig cc runs the clang frontend with -march=native the other being that various clang sanitizers are enabled by default in non-optimized modes.

E.g. you could try if your clang/clang++ build also fails the same way when you explicitly add the -march=native command line option.

A solution might be to provide a generic target triple so that the zig cc build will not attempt to use AVX instruction.

I’m not sure what the best solution is if you actually want to use AVX (but the error message seems to provide a hint that evex512 is needed (whatever that is).

2 Likes

I only had a quick glance at the Skia source code so consider this guesswork, I could be completely wrong. Assuming you’re compiling for your native target, I suspect that the problem is that Skia detects that your CPU supports AVX512 but then goes on to use features that technically also require evex512, which the Zig compiler has not detected/enabled for your CPU model.

I haven’t tried this, but I would first start by trying to explicitly enabling it with

cc="zig cc -target-feature +evex512"
cxx="zig c++ -target-feature +evex512"

but be aware that this could cause issues if your CPU truly doesn’t support this feature. Another potential recourse seeing if there’s some option you can pass to Skia to tell it to not enable AVX512.

2 Likes

With

cc="clang -march=native"
cxx="clang++ -march=native"

the build also succeeded.

My notebook is old. It supports avx2 but not avx512.
The current BUILD.gn in the skia project doesn’t provide an options to disable avx512. I commented out the following lines in it but the zig compiler build still failed with the same errors.

# defines += [ "SK_ENABLE_AVX512_OPTS" ]

  deps = [
...
    #":skx",
...
  ]

After adding extra_cflags=["-DSKCMS_PORTABLE"] as gn argument, the avx errors go, but some other new errors come. The new errors look related to some definitions. Strangely, clang build doesn’t need the definitions. I stopped here.

I tried this, but it looks the options are invalid.

I’m a newbie in c/c++ compiler options. I tried the -mno-avx512f compiler option, but it doesn’t help too.

That should be -Xclang -target-feature -Xclang +evex512.

2 Likes

Yes, these are valid. Without extra_cflags=["-DSKCMS_PORTABLE"], they indeed remove all the avx errors. Now the same situation as where I stopped here: some new errors related to missing some definitions come. But the clang build doesn’t need these definitions.

Could you post the output of zig build-exe --show-builtin on your machine?

Also, what definitions?

const std = @import("std");
/// Zig version. When writing code that supports multiple versions of Zig, prefer
/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
pub const zig_version_string = "0.14.1";
pub const zig_backend = std.builtin.CompilerBackend.stage2_llvm;

pub const output_mode: std.builtin.OutputMode = .Exe;
pub const link_mode: std.builtin.LinkMode = .static;
pub const unwind_tables: std.builtin.UnwindTables = .@"async";
pub const is_test = false;
pub const single_threaded = false;
pub const abi: std.Target.Abi = .gnu;
pub const cpu: std.Target.Cpu = .{
    .arch = .x86_64,
    .model = &std.Target.x86.cpu.haswell,
    .features = std.Target.x86.featureSet(&.{
        .@"64bit",
        .aes,
        .allow_light_256_bit,
        .avx,
        .avx2,
        .bmi,
        .bmi2,
        .cmov,
        .crc32,
        .cx16,
        .cx8,
        .ermsb,
        .f16c,
        .false_deps_lzcnt_tzcnt,
        .false_deps_popcnt,
        .fast_15bytenop,
        .fast_scalar_fsqrt,
        .fast_shld_rotate,
        .fast_variable_crosslane_shuffle,
        .fast_variable_perlane_shuffle,
        .fma,
        .fsgsbase,
        .fxsr,
        .idivq_to_divl,
        .invpcid,
        .lzcnt,
        .macrofusion,
        .mmx,
        .movbe,
        .no_bypass_delay_mov,
        .no_bypass_delay_shuffle,
        .nopl,
        .pclmul,
        .popcnt,
        .rdrnd,
        .sahf,
        .slow_3ops_lea,
        .smep,
        .sse,
        .sse2,
        .sse3,
        .sse4_1,
        .sse4_2,
        .ssse3,
        .vzeroupper,
        .x87,
        .xsave,
        .xsaveopt,
    }),
};
pub const os: std.Target.Os = .{
    .tag = .linux,
    .version_range = .{ .linux = .{
        .range = .{
            .min = .{
                .major = 6,
                .minor = 1,
                .patch = 0,
            },
            .max = .{
                .major = 6,
                .minor = 1,
                .patch = 0,
            },
        },
        .glibc = .{
            .major = 2,
            .minor = 36,
            .patch = 0,
        },
        .android = 14,
    }},
};
pub const target: std.Target = .{
    .cpu = cpu,
    .os = os,
    .abi = abi,
    .ofmt = object_format,
    .dynamic_linker = .init("/lib64/ld-linux-x86-64.so.2"),
};
pub const object_format: std.Target.ObjectFormat = .elf;
pub const mode: std.builtin.OptimizeMode = .Debug;
pub const link_libc = false;
pub const link_libcpp = false;
pub const have_error_return_tracing = true;
pub const valgrind_support = true;
pub const sanitize_thread = false;
pub const fuzz = false;
pub const position_independent_code = false;
pub const position_independent_executable = false;
pub const strip_debug_info = false;
pub const code_model: std.builtin.CodeModel = .default;
pub const omit_frame_pointer = false;

Such as "-DXML_GE=1",