Search code examples
c++cmacosclang

Compile LLVM from sources on macOS Catalina (How to solve "stdio.h" not found)


I'm bringing to your attention a question I tackled with for a few days and no issue could solve for me, in the hope that it'll save some other people time.

I try to compile LLVM from sources on macOS Catalina (10.15).

To do so, I used the following commands (after following the LLVM build manual):

git clone https://github.com/llvm/llvm-project
cd llvm-project
mkdir build && cd build
cmake -G "Ninja" -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE="Debug" ../llvm
ninja

Now you should have a working clang compiler under build/bin. However, given /tmp/program.c with this contents:

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

I got the following output:

/tmp/program.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^~~~~~~~~
1 error generated.

I tried a lot of solutions, including setting CPATH, CFLAGS, CXXFLAGS, LDFLAGS etc but none worked.


Solution

  • System headers new path

    Since macOS Catalina, the /usr folder is been mounted as a read-only directory, so even as a root - no one has permission to modify this folder (well, unless you reboot in SIP mode, which's obviously not a considerable solution). The entire toolchain is saved by default under /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk. You can get your path by executing xcrun --show-sdk-path. I'll assume that you do have the default path in my answer but please adjust as needed.

    Gathering information

    Running clang with the -v flag gave me the following:

    ./clang /tmp/program.c -v --    
    clang version 11.0.0 (https://github.com/llvm/llvm-project 01641197ee0bd3895c756c925723c8c8e03bcb09)
    Target: x86_64-apple-darwin19.5.0
    Thread model: posix
    InstalledDir: ~/llvm/llvm-project/build/bin/.
     "~/llvm/llvm-project/build/bin/clang-11" -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -main-file-name program.c -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fno-rounding-math -munwind-tables -fcompatibility-qualified-id-block-type-checking -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 556.6 -v -resource-dir ~/llvm/llvm-project/build/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem ~/llvm/llvm-project/build/lib/clang/11.0.0/include -internal-externc-isystem /usr/include -fdebug-compilation-dir ~/llvm/llvm-project/build/bin -ferror-limit 19 -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fmax-type-align=16 -fcolor-diagnostics -o /var/folders/64/6bf82c_52ws1n4cwc376znvr0000gn/T/program-d111a4.o -x c /tmp/program.c
    clang -cc1 version 11.0.0 based upon LLVM 11.0.0git default target x86_64-apple-darwin19.5.0
    ignoring nonexistent directory "/usr/include"
    #include "..." search starts here:
    #include <...> search starts here:
     /usr/local/include
     ~/llvm/llvm-project/build/lib/clang/11.0.0/include
     /System/Library/Frameworks (framework directory)
     /Library/Frameworks (framework directory)
    End of search list.
    /tmp/program.c:1:10: fatal error: 'stdio.h' file not found
    #include <stdio.h>
             ^~~~~~~~~
    1 error generated.
    

    Which can teach us that our include paths for system headers are:

    /usr/local/include
    ~/llvm/llvm-project/build/lib/clang/11.0.0/include
    /System/Library/Frameworks (framework directory)
    /Library/Frameworks (framework directory)
    

    Hence, we can see that the location of the new headers (/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk) doesn't appear here and thus the error.

    We could do a symbolic link from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk to /usr/local/include, but that'd create conflicting headers and have bad side effects (yes, I tried. Yes, it was very stupid...).

    Solution

    We can see that one of the default search headers path appears under the build directory (~/llvm/llvm-project/build/lib/clang/11.0.0/include). Symbolic-linking the standard headers to this directory won't create any dangerous conflicts.

    Hence, all you need to do to solve this issue, is:

    ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/* ~/llvm/llvm-project/build/lib/clang/11.0
    

    I hope that my answer will help others who struggle with this issue.