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

search path demotion for llvm headers when building self-hosted with custom llvm-dependency #12888

Closed
mikdusan opened this issue Sep 17, 2022 · 6 comments · Fixed by #12898
Closed
Labels
bug Observed behavior contradicts documented or intended behavior zig build system std.Build, the build runner, `zig build` subcommand, package management
Milestone

Comments

@mikdusan
Copy link
Member

mikdusan commented Sep 17, 2022

Zig Version

0.10.0-dev.4110+dfcadd22b

Steps to Reproduce

  1. on archlinux...
  2. install a version of llvm/clang/lld packages (so that headers are present in /usr/include) that are incompatible (eg. too old) to build zig against. This creates an interference with a custom llvm that you have built to build zig against.
  3. build zig as per usual against custom llvm, expect building stage1 and stage2 to succeed, but stage3 to fail.

Expected Behavior

self-hosted build to succeed

Actual Behavior

self-hosted build fails because the wrong llvm header version is picked up and in this case zig's code is using a function that does not exist in /usr/include's version.

error(compilation): clang failed with stderr: /home/mike/project/zig/work/main/src/stage1/codegen.cpp:4826:17: error: use of undeclared identifier 'LLVMPointerTypeInContext'
/home/mike/project/zig/work/main/src/stage1/codegen.cpp:5171:17: error: use of undeclared identifier 'LLVMPointerTypeInContext'

/home/mike/project/zig/work/main/src/stage1/codegen.cpp:1:1: error: unable to build C object: clang exited with code 1
error: zig...
error: The following command exited with error code 1:
/home/mike/project/zig/work/main/_build/zig2 build-exe --stack 33554432 /home/mike/project/zig/work/main/src/stage1.zig -lc -cflags -std=c++14 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces -Wno-comment -- /home/mike/project/zig/work/main/src/stage1/analyze.cpp /home/mike/project/zig/work/main/src/stage1/astgen.cpp /home/mike/project/zig/work/main/src/stage1/bigfloat.cpp /home/mike/project/zig/work/main/src/stage1/bigint.cpp /home/mike/project/zig/work/main/src/stage1/buffer.cpp /home/mike/project/zig/work/main/src/stage1/codegen.cpp /home/mike/project/zig/work/main/src/stage1/errmsg.cpp /home/mike/project/zig/work/main/src/stage1/error.cpp /home/mike/project/zig/work/main/src/stage1/heap.cpp /home/mike/project/zig/work/main/src/stage1/ir.cpp /home/mike/project/zig/work/main/src/stage1/ir_print.cpp /home/mike/project/zig/work/main/src/stage1/mem.cpp /home/mike/project/zig/work/main/src/stage1/os.cpp /home/mike/project/zig/work/main/src/stage1/parser.cpp /home/mike/project/zig/work/main/src/stage1/range_set.cpp /home/mike/project/zig/work/main/src/stage1/stage1.cpp /home/mike/project/zig/work/main/src/stage1/target.cpp /home/mike/project/zig/work/main/src/stage1/tokenizer.cpp /home/mike/project/zig/work/main/src/stage1/util.cpp /home/mike/project/zig/work/main/src/stage1/softfloat_ext.cpp -cflags -std=c99 -O3 -- /home/mike/project/zig/work/main/src/stage1/parse_f128.c /home/mike/project/zig/work/main/zig-cache/o/64d8a8cd48ea62ba1ffd9f5e9f0eaca8/libsoftfloat.a -lc++ /home/mike/project/zig/work/main/_build/zigcpp/libzigcpp.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangFrontendTool.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangCodeGen.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangFrontend.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangDriver.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangSerialization.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangSema.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangStaticAnalyzerFrontend.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangStaticAnalyzerCheckers.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangStaticAnalyzerCore.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangAnalysis.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangASTMatchers.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangAST.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangParse.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangSema.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangBasic.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangEdit.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangLex.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangARCMigrate.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangRewriteFrontend.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangRewrite.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangCrossTU.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangIndex.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangToolingCore.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangExtractAPI.a /opt/llvm-linux-x86_64-15.0.0-release/lib/libclangSupport.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldMinGW.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldELF.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldCOFF.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldWasm.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldMachO.a /opt/llvm-linux-x86_64-15.0.0-release/lib/liblldCommon.a -lLLVMWindowsManifest -lLLVMWindowsDriver -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lLLVMCoverage -lLLVMLineEditor -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMX86TargetMCA -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyUtils -lLLVMWebAssemblyInfo -lLLVMVEDisassembler -lLLVMVEAsmParser -lLLVMVECodeGen -lLLVMVEDesc -lLLVMVEInfo -lLLVMSystemZDisassembler -lLLVMSystemZAsmParser -lLLVMSystemZCodeGen -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSparcDisassembler -lLLVMSparcAsmParser -lLLVMSparcCodeGen -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMRISCVDisassembler -lLLVMRISCVAsmParser -lLLVMRISCVCodeGen -lLLVMRISCVDesc -lLLVMRISCVInfo -lLLVMPowerPCDisassembler -lLLVMPowerPCAsmParser -lLLVMPowerPCCodeGen -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMMSP430Disassembler -lLLVMMSP430AsmParser -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMipsDisassembler -lLLVMMipsAsmParser -lLLVMMipsCodeGen -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMLanaiDisassembler -lLLVMLanaiCodeGen -lLLVMLanaiAsmParser -lLLVMLanaiDesc -lLLVMLanaiInfo -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonAsmParser -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMBPFDisassembler -lLLVMBPFAsmParser -lLLVMBPFCodeGen -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMAVRDisassembler -lLLVMAVRAsmParser -lLLVMAVRCodeGen -lLLVMAVRDesc -lLLVMAVRInfo -lLLVMARMDisassembler -lLLVMARMAsmParser -lLLVMARMCodeGen -lLLVMARMDesc -lLLVMARMUtils -lLLVMARMInfo -lLLVMAMDGPUTargetMCA -lLLVMAMDGPUDisassembler -lLLVMAMDGPUAsmParser -lLLVMAMDGPUCodeGen -lLLVMAMDGPUDesc -lLLVMAMDGPUUtils -lLLVMAMDGPUInfo -lLLVMAArch64Disassembler -lLLVMAArch64AsmParser -lLLVMAArch64CodeGen -lLLVMAArch64Desc -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMOrcJIT -lLLVMMCJIT -lLLVMJITLink -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMOrcTargetProcess -lLLVMOrcShared -lLLVMDWP -lLLVMDebugInfoGSYM -lLLVMOption -lLLVMObjectYAML -lLLVMObjCopy -lLLVMMCA -lLLVMMCDisassembler -lLLVMLTO -lLLVMPasses -lLLVMCFGuard -lLLVMCoroutines -lLLVMObjCARCOpts -lLLVMipo -lLLVMVectorize -lLLVMLinker -lLLVMInstrumentation -lLLVMFrontendOpenMP -lLLVMFrontendOpenACC -lLLVMExtensions -lLLVMDWARFLinker -lLLVMGlobalISel -lLLVMMIRParser -lLLVMAsmPrinter -lLLVMSelectionDAG -lLLVMCodeGen -lLLVMIRReader -lLLVMAsmParser -lLLVMInterfaceStub -lLLVMFileCheck -lLLVMFuzzMutate -lLLVMTarget -lLLVMScalarOpts -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMSymbolize -lLLVMDebugInfoPDB -lLLVMDebugInfoMSF -lLLVMDebugInfoDWARF -lLLVMObject -lLLVMTextAPI -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMBitReader -lLLVMFuzzerCLI -lLLVMCore -lLLVMRemarks -lLLVMBitstreamReader -lLLVMBinaryFormat -lLLVMTableGen -lLLVMSupport -lLLVMDemangle -lz /usr/lib/libzstd.so.1.5.2 /usr/lib/libstdc++.a -lunwind --cache-dir /home/mike/project/zig/work/main/zig-cache --global-cache-dir /home/mike/project/zig/work/main/zig-cache --name zig -target native-native -mcpu x86_64 --pkg-begin build_options /home/mike/project/zig/work/main/zig-cache/options/KT8v3sbeg53FNRkM2eKXbC07S8ZLh5UxAz4nTa54ORvuj1RFHAi8T-ztgwOol43P --pkg-end --pkg-begin compiler_rt /home/mike/project/zig/work/main/src/empty.zig --pkg-end -I /home/mike/project/zig/work/main/src -I /home/mike/project/zig/work/main/deps/SoftFloat-3e/source/include -I /home/mike/project/zig/work/main/deps/SoftFloat-3e-prebuilt -I /opt/llvm-linux-x86_64-15.0.0-release/include -I /opt/BOGUS_WTF -D ZIG_LINK_MODE=Static -L /opt/llvm-linux-x86_64-15.0.0-release/lib -isystem /opt/llvm-linux-x86_64-15.0.0-release/include -fno-build-id --zig-lib-dir /home/mike/project/zig/work/main/lib --enable-cache

To further drill down, after the failure, add --verbose-cc to the failed zig2 build-exe command to get the zig2 clang command where we add -v to show header search path:

 "/home/mike/project/zig/work/main/_build/zig2" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name codegen.cpp -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -mllvm -treat-scalable-fixed-error-as-warning -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -v -fcoverage-compilation-dir=/home/mike/project/zig/work/main -nostdsysteminc -nobuiltininc -resource-dir /home/mike/project/zig/work/main/lib/clang/15.0.0 -dependency-file /home/mike/project/zig/work/main/zig-cache/tmp/b72e986cfa10b073-codegen.o.d -MT /home/mike/project/zig/work/main/zig-cache/tmp/b72e986cfa10b073-codegen.o -sys-header-deps -MV -isystem /home/mike/project/zig/work/main/lib/libcxx/include -isystem /home/mike/project/zig/work/main/lib/libcxxabi/include -isystem /home/mike/project/zig/work/main/lib/libunwind/include -isystem /home/mike/project/zig/work/main/lib/include -isystem /usr/include -isystem /opt/llvm-linux-x86_64-15.0.0-release/include -isystem /usr/local/include -isystem /usr/include/x86_64-linux-gnu -isystem /usr/include -D _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D _LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -D _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -D _LIBCPP_ABI_VERSION=1 -D _LIBCPP_ABI_NAMESPACE=__1 -D __GLIBC_MINOR__=36 -D _DEBUG -I /home/mike/project/zig/work/main/src -I /home/mike/project/zig/work/main/deps/SoftFloat-3e/source/include -I /home/mike/project/zig/work/main/deps/SoftFloat-3e-prebuilt -I /opt/llvm-linux-x86_64-15.0.0-release/include -I /opt/BOGUS_WTF -D ZIG_LINK_MODE=Static -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D _GNU_SOURCE -O0 -Werror=type-limits -Wno-missing-braces -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/home/mike/project/zig/work/main -ferror-limit 19 -fvisibility-inlines-hidden -fsanitize=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound -fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound -stack-protector 2 -stack-protector-buffer-size 4 -fno-rtti -fgnuc-version=4.2.1 -fno-caret-diagnostics -fcolor-diagnostics -fno-spell-checking -target-cpu x86-64 -target-feature -16bit-mode -target-feature -32bit-mode -target-feature -3dnow -target-feature -3dnowa -target-feature +64bit -target-feature -adx -target-feature -aes -target-feature -amx-bf16 -target-feature -amx-int8 -target-feature -amx-tile -target-feature -avx -target-feature -avx2 -target-feature -avx512bf16 -target-feature -avx512bitalg -target-feature -avx512bw -target-feature -avx512cd -target-feature -avx512dq -target-feature -avx512er -target-feature -avx512f -target-feature -avx512fp16 -target-feature -avx512ifma -target-feature -avx512pf -target-feature -avx512vbmi -target-feature -avx512vbmi2 -target-feature -avx512vl -target-feature -avx512vnni -target-feature -avx512vp2intersect -target-feature -avx512vpopcntdq -target-feature -avxvnni -target-feature -bmi -target-feature -bmi2 -target-feature -branchfusion -target-feature -cldemote -target-feature -clflushopt -target-feature -clwb -target-feature -clzero -target-feature +cmov -target-feature -crc32 -target-feature -cx16 -target-feature +cx8 -target-feature -enqcmd -target-feature -ermsb -target-feature -f16c -target-feature -false-deps-getmant -target-feature -false-deps-lzcnt-tzcnt -target-feature -false-deps-mulc -target-feature -false-deps-mullq -target-feature -false-deps-perm -target-feature -false-deps-popcnt -target-feature -false-deps-range -target-feature -fast-11bytenop -target-feature -fast-15bytenop -target-feature -fast-7bytenop -target-feature -fast-bextr -target-feature -fast-gather -target-feature -fast-hops -target-feature -fast-lzcnt -target-feature -fast-movbe -target-feature -fast-scalar-fsqrt -target-feature -fast-scalar-shift-masks -target-feature -fast-shld-rotate -target-feature -fast-variable-crosslane-shuffle -target-feature -fast-variable-perlane-shuffle -target-feature -fast-vector-fsqrt -target-feature -fast-vector-shift-masks -target-feature -fma -target-feature -fma4 -target-feature -fsgsbase -target-feature -fsrm -target-feature +fxsr -target-feature -gfni -target-feature -harden-sls-ijmp -target-feature -harden-sls-ret -target-feature -hreset -target-feature -idivl-to-divb -target-feature +idivq-to-divl -target-feature -invpcid -target-feature -kl -target-feature -lea-sp -target-feature -lea-uses-ag -target-feature -lvi-cfi -target-feature -lvi-load-hardening -target-feature -lwp -target-feature -lzcnt -target-feature +macrofusion -target-feature +mmx -target-feature -movbe -target-feature -movdir64b -target-feature -movdiri -target-feature -mwaitx -target-feature +nopl -target-feature -pad-short-functions -target-feature -pclmul -target-feature -pconfig -target-feature -pku -target-feature -popcnt -target-feature -prefer-128-bit -target-feature -prefer-256-bit -target-feature -prefer-mask-registers -target-feature -prefetchwt1 -target-feature -prfchw -target-feature -ptwrite -target-feature -rdpid -target-feature -rdpru -target-feature -rdrnd -target-feature -rdseed -target-feature -retpoline -target-feature -retpoline-external-thunk -target-feature -retpoline-indirect-branches -target-feature -retpoline-indirect-calls -target-feature -rtm -target-feature -sahf -target-feature -sbb-dep-breaking -target-feature -serialize -target-feature -seses -target-feature -sgx -target-feature -sha -target-feature -shstk -target-feature +slow-3ops-lea -target-feature +slow-incdec -target-feature -slow-lea -target-feature -slow-pmaddwd -target-feature -slow-pmulld -target-feature -slow-shld -target-feature -slow-two-mem-ops -target-feature -slow-unaligned-mem-16 -target-feature -slow-unaligned-mem-32 -target-feature -soft-float -target-feature +sse -target-feature +sse2 -target-feature -sse3 -target-feature -sse4.1 -target-feature -sse4.2 -target-feature -sse4a -target-feature -sse-unaligned-mem -target-feature -ssse3 -target-feature -tagged-globals -target-feature -tbm -target-feature -tsxldtrk -target-feature -uintr -target-feature -use-glm-div-sqrt-costs -target-feature -use-slm-arith-costs -target-feature -vaes -target-feature -vpclmulqdq -target-feature +vzeroupper -target-feature -waitpkg -target-feature -wbnoinvd -target-feature -widekl -target-feature +x87 -target-feature -xop -target-feature -xsave -target-feature -xsavec -target-feature -xsaveopt -target-feature -xsaves -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/mike/project/zig/work/main/zig-cache/tmp/b72e986cfa10b073-codegen.o -x c++ /home/mike/project/zig/work/main/src/stage1/codegen.cpp
clang -cc1 version 15.0.0 based upon LLVM 15.0.0 default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/opt/BOGUS_WTF"
ignoring nonexistent directory "/usr/include/x86_64-linux-gnu"
ignoring duplicate directory "/opt/llvm-linux-x86_64-15.0.0-release/include"
  as it is a non-system directory that duplicates a system directory
ignoring duplicate directory "/usr/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/mike/project/zig/work/main/src
 /home/mike/project/zig/work/main/deps/SoftFloat-3e/source/include
 /home/mike/project/zig/work/main/deps/SoftFloat-3e-prebuilt
 /home/mike/project/zig/work/main/lib/libcxx/include
 /home/mike/project/zig/work/main/lib/libcxxabi/include
 /home/mike/project/zig/work/main/lib/libunwind/include
 /home/mike/project/zig/work/main/lib/include
 /usr/include
 /opt/llvm-linux-x86_64-15.0.0-release/include
 /usr/local/include
End of search list.

The issue cause is /opt/llvm-linux-x86_64-15.0.0-release/include (my custom llvm location) comes after /usr/include. The reasoning for this is a detail in clang command-line parsing. Here's what happens.

  1. zig adds arg -I /opt/llvm-linux-x86_64-15.0.0-release/include. This is good.
  2. zig adds arg (or already has added) -isystem /usr/include. This is good.
  3. zig adds arg -isystem /opt/llvm-linux-x86_64-15.0.0-release/include. This bad as it interferes with previous -I option. clang's beheaviour is to group -I searches together, in order as first seen on command-line. It also groups -isystem searches together as first seen on command line and in the end, the absolute search list first searches all -I dirs, then it searches all -isystem dirs. When clang gets a -isystem dir that interferes with -I it silently removes the dir from -I and adds it to -isystem, in effect demoting the search precedence of the dir.

I think we've had this behaviour for quite some time, and it explains a lot of "fuzzy" build issue reports with self-hosted people have been having over the last(?) year when a different version of llvm is already installed in a standard OS location such as /usr/include.

So what's the cause? This bit of code assumes search-prefix headers are -isystem. A simple fix may be to change this code to use -I. The other annoyance is we shouldn't have llvm headers listed twice on the command line. AFAICT, duplicate search dirs, as long as they use the same command switch, are harmless:

zig/lib/std/build.zig

Lines 3122 to 3125 in 2c3d87b

try zig_args.append("-isystem");
try zig_args.append(builder.pathJoin(&.{
search_prefix, "include",
}));

note: the workaround to this issue is to temporarily remove the interfering llvm package from system

@mikdusan mikdusan added bug Observed behavior contradicts documented or intended behavior zig build system std.Build, the build runner, `zig build` subcommand, package management labels Sep 17, 2022
@matu3ba
Copy link
Contributor

matu3ba commented Sep 17, 2022

The other annoyance is we shouldn't have llvm headers listed twice on the command line

Note, that the cause of this specific issue can be isolated to zig code:

set(ZIG_INSTALL_ARGS "build"
    --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
    --prefix "${CMAKE_INSTALL_PREFIX}"
    "-Dconfig_h=${ZIG_CONFIG_H_OUT}"
    "-Denable-llvm"
    "-Denable-stage1"
    ${ZIG_RELEASE_ARG}
    ${ZIG_STATIC_ARG}
    ${ZIG_SKIP_INSTALL_LIB_FILES_ARG}
    ${ZIG_SINGLE_THREADED_ARG}
    "-Dtarget=${ZIG_TARGET_TRIPLE}"
    "-Dcpu=${ZIG_TARGET_MCPU}"
    "-Dversion-string=${ZIG_VERSION}"
)

add_custom_target(stage3 ALL
    COMMAND zig2 ${ZIG_INSTALL_ARGS}
    DEPENDS zig2
    COMMENT STATUS "Building stage3"
    WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)

Do you have any opinion on how one could eliminate this slippery slope from clang?
Or at least make it easier to diagnose, if one has a wrong search order of things?

  1. Is there no clang instrumentation to query "the end result of resolving -isystem and -I rules to know where clang is looking for things by what is given on the filesystem?
  2. Reducing manually clang invocation paths is unnecessary time-consuming. Try to imagine you need to do this for packaging. How should such a build flag be called? This requires having build-singlethreaded and reading the output of zig clang calls on error to print clang calls nicely.
  3. Long-term it would be nice to properly resolve things under Zig build system control and then emitting the clang arguments.

@matu3ba
Copy link
Contributor

matu3ba commented Sep 17, 2022

Response in chat by @mikdusan

How include paths given by build.zig currently work

It looks to me like the precedence is generally user-specified paths get highest priority but they do land in 1 of 2 groups, and for lack of better nomenclature I'll just call it -I and -isystem groups and it looks to me the search order is basically this (lower number is searched first)

1. user-specified -I
2. zig-logic specified -I
3. user-specified -isystem
4. zig-logic specified -isystem

and all are governed by duplicates are essentially ignored. ie: duplicating a -I doesn't cause it to be searched last.
but... duplicating the same path in -I and -isystem is the goofy demotion behaviour that I opened issue for

To prevent this (major) clang footgun we could:

1. adding superfluous -I gets a warning (or ignored?)
2. adding the same dir to both -I and -isystem groups gets a warning (or error?)

other workaround:

diff --git a/lib/std/build.zig b/lib/std/build.zig
index 2c141d540..50fcad9f8 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -3119,7 +3119,7 @@ pub const LibExeObjStep = struct {
             try zig_args.append(builder.pathJoin(&.{
                 search_prefix, "lib",
             }));
-            try zig_args.append("-isystem");
+            try zig_args.append("-I");
             try zig_args.append(builder.pathJoin(&.{
                 search_prefix, "include",
             }));

@mikdusan
Copy link
Member Author

To prevent this (major) clang footgun we could:

1. adding superfluous -I gets a warning (or ignored?)
2. adding the same dir to both -I and -isystem groups gets a warning (or error?)

Hmm after thinking about this some more I think the behaviour may need to be more forgiving.

Consider if you have a project that has all dependencies installed in separate dirs. Like so:

  • /opt/moduleA with /opt/moduleA/include
  • /opt/moduleB with /opt/moduleB/include

then there is generally never going to be conflict.

But let's say a maintainer decides to fold all deps into one tree:

  • /opt/all with /opt/all/include

typical logic would be:

  • b.addSystemIncludePath(MODULE_A_ROOT ++ "/include")
  • b.addSystemIncludePath(MODULE_B_ROOT ++ "/include")

and if MODULE_A_ROOT == MODULE_B_ROOT, I think it would be too much friction to force people to check this.
Instead, I'm leaning towards a forgiving approach:

  1. superfluous -I is allowed and silently ignored
  2. superfluous -isystem is allowed and silently ignored
  3. same dir added to both -I and -isystem and a warning is issued

@edt-xx
Copy link

edt-xx commented Sep 18, 2022

Adding the patch above along along with a -DCMAKE_PREFIX_PATH=$HOME/local/llvm15 to the PKGBUILD for zig-git (Arch Linux) allows it to work with a private copy of LLVM.

@mikdusan
Copy link
Member Author

mikdusan commented Sep 18, 2022

found this tidbit from gcc docs; which clang and the notes in this issue are consistent with:

If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option is ignored. The directory is still searched but as a system directory at its normal position in the system include chain.

mikdusan added a commit to mikdusan/zig that referenced this issue Sep 18, 2022
build.zig:
- use "-I" instead of "-isystem" for `b.addSearchPrefix()`

main.zig:
- silently ignore superfluous search dirs
- warn when a dir is added to multiple searchlists
- consolidate "expected paramter after {s}" fatal error messages

closes ziglang#12888
mikdusan added a commit to mikdusan/zig that referenced this issue Sep 19, 2022
build.zig:
- use "-I" instead of "-isystem" for `b.addSearchPrefix()`

main.zig:
- silently ignore superfluous search dirs
- warn when a dir is added to multiple searchlists
- consolidate "expected paramter after {s}" fatal error messages
- rename command-line switch `-dirafter` → `-idirafter`

closes ziglang#12888
@matu3ba
Copy link
Contributor

matu3ba commented Sep 20, 2022

This is related to #11801

andrewrk pushed a commit that referenced this issue Oct 12, 2022
build.zig:
- use "-I" instead of "-isystem" for `b.addSearchPrefix()`

main.zig:
- silently ignore superfluous search dirs
- warn when a dir is added to multiple searchlists
- consolidate "expected paramter after {s}" fatal error messages
- rename command-line switch `-dirafter` → `-idirafter`

closes #12888
@andrewrk andrewrk added this to the 0.10.0 milestone Oct 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior zig build system std.Build, the build runner, `zig build` subcommand, package management
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants