Skip to content

[runtimes] [openmp] -nostdlib++ added to CMAKE_REQUIRED_FLAGS breaks hwloc detection for OMPT #90332

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

Open
mgorny opened this issue Apr 27, 2024 · 22 comments · Fixed by #108357
Open
Assignees
Labels
cmake Build system in general and CMake in particular openmp

Comments

@mgorny
Copy link
Member

mgorny commented Apr 27, 2024

To reproduce:

$ cmake -G Ninja -DLLVM_ENABLE_RUNTIMES=openmp -DLIBOMP_USE_HWLOC=ON ${path_to_llvm_project}/runtimes
[…]
-- Looking for hwloc.h
-- Looking for hwloc.h - not found
-- Looking for hwloc_topology_init in /usr/lib64/libhwloc.so
-- Looking for hwloc_topology_init in /usr/lib64/libhwloc.so - not found
-- LIBOMP: Could not find hwloc
CMake Error at /home/mgorny/git/llvm-project/openmp/runtime/cmake/LibompUtils.cmake:26 (message):
  LIBOMP: Hwloc requested but not available
Call Stack (most recent call first):
  /home/mgorny/git/llvm-project/openmp/runtime/CMakeLists.txt:387 (libomp_error_say)


-- Configuring incomplete, errors occurred!

CMakeFiles/CMakeConfigureLog.yaml hints at the problem:

  -
    kind: "try_compile-v1"
    backtrace:
      - "/usr/share/cmake/Modules/CheckIncludeFile.cmake:90 (try_compile)"
      - "/home/mgorny/git/llvm-project/openmp/runtime/cmake/config-ix.cmake:351 (check_include_file)"
      - "/home/mgorny/git/llvm-project/openmp/runtime/CMakeLists.txt:276 (include)"
    checks:
      - "Looking for hwloc.h"
    directories:
      source: "/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY"
      binary: "/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY"
    cmakeVariables:
      CMAKE_C_FLAGS: " -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections"
      CMAKE_C_FLAGS_DEBUG: "-g"
      CMAKE_EXE_LINKER_FLAGS: ""
      CMAKE_MODULE_PATH: "/home/mgorny/git/llvm-project/openmp/runtime/cmake;/home/mgorny/git/llvm-project/openmp/cmake;/home/mgorny/git/llvm-project/openmp/../cmake/Modules;/home/mgorny/git/llvm-project/runtimes/cmake;/home/mgorny/git/llvm-project/runtimes/cmake/modules;/home/mgorny/git/llvm-project/runtimes/../cmake;/home/mgorny/git/llvm-project/runtimes/../cmake/Modules;/home/mgorny/git/llvm-project/runtimes/../llvm/cmake;/home/mgorny/git/llvm-project/runtimes/../llvm/cmake/modules"
    buildResult:
      variable: "LIBOMP_HAVE_HWLOC_H"
      cached: true
      stdout: |
        Change Dir: '/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY'
        
        Run Build Command(s): /usr/bin/ninja -v cmTC_5eb96
        [1/2] /usr/bin/cc   -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections  -nostdlib++ -nostdinc++ -o CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o -c /home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY/CheckIncludeFile.c
        FAILED: CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o 
        /usr/bin/cc   -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections  -nostdlib++ -nostdinc++ -o CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o -c /home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY/CheckIncludeFile.c
        cc: error: unrecognized command-line option ‘-nostdlib++’
        ninja: build stopped: subcommand failed.
        
      exitCode: 1

i.e. the nostdlib++ flags gets appended to both C and C++ compiler flags, effectively breaking all compilations done in C mode.

CC @mstorsjo as the one who added the logic

@mgorny mgorny added cmake Build system in general and CMake in particular openmp labels Apr 27, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 27, 2024

@llvm/issue-subscribers-openmp

Author: Michał Górny (mgorny)

To reproduce:
$ cmake -G Ninja -DLLVM_ENABLE_RUNTIMES=openmp -DLIBOMP_USE_HWLOC=ON ${path_to_llvm_project}/runtimes
[…]
-- Looking for hwloc.h
-- Looking for hwloc.h - not found
-- Looking for hwloc_topology_init in /usr/lib64/libhwloc.so
-- Looking for hwloc_topology_init in /usr/lib64/libhwloc.so - not found
-- LIBOMP: Could not find hwloc
CMake Error at /home/mgorny/git/llvm-project/openmp/runtime/cmake/LibompUtils.cmake:26 (message):
  LIBOMP: Hwloc requested but not available
Call Stack (most recent call first):
  /home/mgorny/git/llvm-project/openmp/runtime/CMakeLists.txt:387 (libomp_error_say)


-- Configuring incomplete, errors occurred!

CMakeFiles/CMakeConfigureLog.yaml hints at the problem:

  -
    kind: "try_compile-v1"
    backtrace:
      - "/usr/share/cmake/Modules/CheckIncludeFile.cmake:90 (try_compile)"
      - "/home/mgorny/git/llvm-project/openmp/runtime/cmake/config-ix.cmake:351 (check_include_file)"
      - "/home/mgorny/git/llvm-project/openmp/runtime/CMakeLists.txt:276 (include)"
    checks:
      - "Looking for hwloc.h"
    directories:
      source: "/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY"
      binary: "/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY"
    cmakeVariables:
      CMAKE_C_FLAGS: " -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections"
      CMAKE_C_FLAGS_DEBUG: "-g"
      CMAKE_EXE_LINKER_FLAGS: ""
      CMAKE_MODULE_PATH: "/home/mgorny/git/llvm-project/openmp/runtime/cmake;/home/mgorny/git/llvm-project/openmp/cmake;/home/mgorny/git/llvm-project/openmp/../cmake/Modules;/home/mgorny/git/llvm-project/runtimes/cmake;/home/mgorny/git/llvm-project/runtimes/cmake/modules;/home/mgorny/git/llvm-project/runtimes/../cmake;/home/mgorny/git/llvm-project/runtimes/../cmake/Modules;/home/mgorny/git/llvm-project/runtimes/../llvm/cmake;/home/mgorny/git/llvm-project/runtimes/../llvm/cmake/modules"
    buildResult:
      variable: "LIBOMP_HAVE_HWLOC_H"
      cached: true
      stdout: |
        Change Dir: '/home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY'
        
        Run Build Command(s): /usr/bin/ninja -v cmTC_5eb96
        [1/2] /usr/bin/cc   -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections  -nostdlib++ -nostdinc++ -o CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o -c /home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY/CheckIncludeFile.c
        FAILED: CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o 
        /usr/bin/cc   -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -Wall -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -fno-semantic-interposition -fdata-sections  -nostdlib++ -nostdinc++ -o CMakeFiles/cmTC_5eb96.dir/CheckIncludeFile.c.o -c /home/mgorny/git/llvm-project/build/CMakeFiles/CMakeScratch/TryCompile-EEYwvY/CheckIncludeFile.c
        cc: error: unrecognized command-line option ‘-nostdlib++’
        ninja: build stopped: subcommand failed.
        
      exitCode: 1

i.e. the nostdlib++ flags gets appended to both C and C++ compiler flags, effectively breaking all compilations done in C mode.

CC @mstorsjo as the one who added the logic

@Chrismarsh
Copy link

I am seeing this when trying to compile llvm 17.0.6. The error is slightly different in that the flag is accepted, however, there are missing symbols.

    kind: "try_compile-v1"
    backtrace:
      - "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/cmake-3.29.6-q6iwwch2crujenzcug42iuvx32hi2mz5/share/cmake-3.29/Modules/CheckLibraryExists.cmake:69 (try_compile)"
      - "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/openmp/runtime/cmake/config-ix.cmake:349 (check_library_exists)"
      - "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/openmp/runtime/CMakeLists.txt:245 (include)"
    checks:
      - "Looking for hwloc_topology_init in /globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib/libhwloc.so"
    directories:
      source: "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/runtimes/runtimes-bins/CMakeFiles/CMakeScratch/TryCompile-XydOOq"
      binary: "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/runtimes/runtimes-bins/CMakeFiles/CMakeScratch/TryCompile-XydOOq"
    cmakeVariables:
      CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS: "CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS-NOTFOUND"
      CMAKE_CXX_COMPILER_TARGET: "x86_64-unknown-linux-gnu"
      CMAKE_C_COMPILER_TARGET: "x86_64-unknown-linux-gnu"
      CMAKE_C_FLAGS: "--gcc-install-dir=/cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12 -fPIC -fno-semantic-interposition -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -Wcast-qual -Wformat-pedantic -Wimplicit-fallthrough -Wsign-compare -Wno-enum-constexpr-conversion -Wno-extra -Wno-pedantic"
      CMAKE_C_FLAGS_DEBUG: "-g"
      CMAKE_EXE_LINKER_FLAGS: ""
      CMAKE_MODULE_PATH: "/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/openmp/runtime/cmake;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/openmp/cmake;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/openmp/../cmake/Modules;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/cmake;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/cmake/modules;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/../cmake;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/../cmake/Modules;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/../llvm/cmake;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-src/runtimes/../llvm/cmake/modules;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/lib/cmake/llvm;/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/lib/cmake/llvm"
    buildResult:
      variable: "LIBOMP_HAVE_LIBHWLOC"
      cached: true
      stdout: |
        Change Dir: '/gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/runtimes/runtimes-bins/CMakeFiles/CMakeScratch/TryCompile-XydOOq'
        
        Run Build Command(s): /globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/ninja-1.12.0-x2csjlvyad6s7gnfoa5ubpncbt3cu3dg/bin/ninja-build -v cmTC_48e41
        [1/2] /gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/bin/clang --target=x86_64-unknown-linux-gnu   --gcc-install-dir=/cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12 -fPIC -fno-semantic-interposition -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -Wcast-qual -Wformat-pedantic -Wimplicit-fallthrough -Wsign-compare -Wno-enum-constexpr-conversion -Wno-extra -Wno-pedantic -DCHECK_FUNCTION_EXISTS=hwloc_topology_init  --start-no-unused-arguments --unwindlib=none --end-no-unused-arguments -nostdlib++ -nostdinc++ -MD -MT CMakeFiles/cmTC_48e41.dir/CheckFunctionExists.c.o -MF CMakeFiles/cmTC_48e41.dir/CheckFunctionExists.c.o.d -o CMakeFiles/cmTC_48e41.dir/CheckFunctionExists.c.o -c /gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/runtimes/runtimes-bins/CMakeFiles/CMakeScratch/TryCompile-XydOOq/CheckFunctionExists.c
        [2/2] : && /gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/bin/clang --target=x86_64-unknown-linux-gnu --gcc-install-dir=/cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12 -fPIC -fno-semantic-interposition -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -Wcast-qual -Wformat-pedantic -Wimplicit-fallthrough -Wsign-compare -Wno-enum-constexpr-conversion -Wno-extra -Wno-pedantic -DCHECK_FUNCTION_EXISTS=hwloc_topology_init  --start-no-unused-arguments --unwindlib=none --end-no-unused-arguments -nostdlib++ -nostdinc++  CMakeFiles/cmTC_48e41.dir/CheckFunctionExists.c.o -o cmTC_48e41 -L/globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib -Wl,-rpath,/globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib  /globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib/libhwloc.so && :
        FAILED: cmTC_48e41 
        : && /gpfs/tp/gwf/gwf_cmt/cmarsh/spack/stage/spack-stage-llvm-17.0.6-siym653rezmksycrvlez7jah5tk72os3/spack-build-siym653/bin/clang --target=x86_64-unknown-linux-gnu --gcc-install-dir=/cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12 -fPIC -fno-semantic-interposition -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -Wcast-qual -Wformat-pedantic -Wimplicit-fallthrough -Wsign-compare -Wno-enum-constexpr-conversion -Wno-extra -Wno-pedantic -DCHECK_FUNCTION_EXISTS=hwloc_topology_init  --start-no-unused-arguments --unwindlib=none --end-no-unused-arguments -nostdlib++ -nostdinc++  CMakeFiles/cmTC_48e41.dir/CheckFunctionExists.c.o -o cmTC_48e41 -L/globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib -Wl,-rpath,/globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib  /globalhome/cbm038/HPC/project/spack/install/linux-rhel9-skylake_avx512/gcc-12.3.1/hwloc-2.9.3-rpi4timtsf6t32tbrgvhkxcwfqxnywhv/lib/libhwloc.so && :
        /cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/x86_64-pc-linux-gnu/binutils-bin/2.41/ld: /cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12/libgcc_s.so.1: undefined reference to `_dl_find_object@GLIBC_2.35'
        /cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/x86_64-pc-linux-gnu/binutils-bin/2.41/ld: /cvmfs/soft.computecanada.ca/gentoo/2023/x86-64-v3/usr/lib/gcc/x86_64-pc-linux-gnu/12/libstdc++.so.6: undefined reference to `arc4random@GLIBC_2.36'
        clang: error: linker command failed with exit code 1 (use -v to see invocation)
        ninja: build stopped: subcommand failed.
        
      exitCode: 1
...

@mstorsjo
Copy link
Member

mstorsjo commented Jul 7, 2024

Sorry, I somehow missed the initial notification on this back in April... I'd like to CC in @petrhosek as well, who also has worked a lot on this aspect.

So I presume the source of these flags is in https://github.com/llvm/llvm-project/blob/llvmorg-19-init/runtimes/CMakeLists.txt#L138-L149. They're quite essential for any probing in C++ mode.

Offhand, I don't have any good idea about how to try to fix this issue. Does @petrhosek have any ideas?

@h-vetinari
Copy link
Contributor

I've run into this with libcxx 18.1.8 on linux, where dl gets misdetected:

-- Looking for dladdr in dl
-- Looking for dladdr in dl - not found
-- Looking for pthread_once in pthread
-- Looking for pthread_once in pthread - not found

and then compilation fails on missing symbols for dladdr. Looking under the hood of that detection failure, it's likewise due to -nostdlib++:

    kind: "try_compile-v1"
    backtrace:
      - "$BUILD_PREFIX/share/cmake-3.30/Modules/CheckLibraryExists.cmake:69 (try_compile)"
      - "$SRC_DIR/libcxxabi/cmake/config-ix.cmake:109 (check_library_exists)"
      - "$SRC_DIR/libcxxabi/CMakeLists.txt:249 (include)"
    checks:
      - "Looking for dladdr in dl"
    directories:
      source: "$SRC_DIR/build/CMakeFiles/CMakeScratch/TryCompile-dRIlTz"
      binary: "$SRC_DIR/build/CMakeFiles/CMakeScratch/TryCompile-dRIlTz"
    cmakeVariables:
      CMAKE_C_FLAGS: "-march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem $PREFIX/include -fdebug-prefix-map=$SRC_DIR=/usr/local/src/conda/libcxx_and_libcxxabi-18.1.8 -fdebug-prefix-map=$PREFIX=/usr/local/src/conda-prefix -I$PREFIX/include -I$BUILD_PREFIX/include -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color"
      CMAKE_C_FLAGS_DEBUG: "-g"
      CMAKE_EXE_LINKER_FLAGS: "-Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,--allow-shlib-undefined -Wl,-rpath,$PREFIX/lib -Wl,-rpath-link,$PREFIX/lib -L$PREFIX/lib -L$PREFIX/lib -Wl,-rpath,$PREFIX/lib -L$BUILD_PREFIX/lib -Wl,-rpath,$BUILD_PREFIX/lib"
      CMAKE_MODULE_PATH: "$SRC_DIR/libcxxabi/cmake;$SRC_DIR/libcxxabi/cmake/Modules;$SRC_DIR/libcxxabi/cmake;$SRC_DIR/libcxxabi/cmake/Modules;$SRC_DIR/libcxxabi/../runtimes/cmake/Modules;$SRC_DIR/libcxxabi/../cmake;$SRC_DIR/libcxxabi/../cmake/Modules;$SRC_DIR/runtimes/cmake;$SRC_DIR/runtimes/cmake/modules;$SRC_DIR/runtimes/../cmake;$SRC_DIR/runtimes/../cmake/Modules;$SRC_DIR/runtimes/../llvm/cmake;$SRC_DIR/runtimes/../llvm/cmake/modules"
    buildResult:
      variable: "LIBCXXABI_HAS_DL_LIB"
      cached: true
      stdout: |
        Change Dir: '$SRC_DIR/build/CMakeFiles/CMakeScratch/TryCompile-dRIlTz'
        
        Run Build Command(s): $BUILD_PREFIX/bin/ninja -v cmTC_c57b3
        [1/2] $BUILD_PREFIX/bin/x86_64-conda-linux-gnu-cc   -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem $PREFIX/include -fdebug-prefix-map=$SRC_DIR=/usr/local/src/conda/libcxx_and_libcxxabi-18.1.8 -fdebug-prefix-map=$PREFIX=/usr/local/src/conda-prefix -I$PREFIX/include -I$BUILD_PREFIX/include -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -DCHECK_FUNCTION_EXISTS=dladdr  -nostdlib++ -nostdinc++ -nostdlib++ -o CMakeFiles/cmTC_c57b3.dir/CheckFunctionExists.c.o -c $SRC_DIR/build/CMakeFiles/CMakeScratch/TryCompile-dRIlTz/CheckFunctionExists.c
        FAILED: CMakeFiles/cmTC_c57b3.dir/CheckFunctionExists.c.o 
        $BUILD_PREFIX/bin/x86_64-conda-linux-gnu-cc   -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem $PREFIX/include -fdebug-prefix-map=$SRC_DIR=/usr/local/src/conda/libcxx_and_libcxxabi-18.1.8 -fdebug-prefix-map=$PREFIX=/usr/local/src/conda-prefix -I$PREFIX/include -I$BUILD_PREFIX/include -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -Wno-comment -fdiagnostics-color -DCHECK_FUNCTION_EXISTS=dladdr  -nostdlib++ -nostdinc++ -nostdlib++ -o CMakeFiles/cmTC_c57b3.dir/CheckFunctionExists.c.o -c $SRC_DIR/build/CMakeFiles/CMakeScratch/TryCompile-dRIlTz/CheckFunctionExists.c
        x86_64-conda-linux-gnu-cc: error: unrecognized command-line option '-nostdlib++'
        x86_64-conda-linux-gnu-cc: error: unrecognized command-line option '-nostdlib++'
        ninja: build stopped: subcommand failed.
        
      exitCode: 1

@Chrismarsh
Copy link

Is there any progress on this or anything else that can be contributed to help?

@mstorsjo
Copy link
Member

mstorsjo commented Sep 2, 2024

I'm trying to wrap my head around why this isn't an issue in more cases than it does currently.

With clang, passing -nostdlib++ while linking with the C mode compiler, isn't an issue.

GCC supports -nostdlib++ since GCC 13, but even there, doing e.g. gcc -nostdlib++ foo.c seems to run fine (tested on Ubuntu 24.04 just now).

The cases where this is an issue - what are the respective C and C++ compilers that are involved in the cmake configurations, where the C++ compiler apparently supports the option, but the C compiler doesn't?

@mgorny
Copy link
Member Author

mgorny commented Sep 2, 2024

$ gcc -nostdlib++ foo.c
gcc: error: unrecognized command-line option ‘-nostdlib++’
$ gcc --version
gcc (Gentoo 14.2.1_p20240817 p4) 14.2.1 20240817
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@mstorsjo
Copy link
Member

mstorsjo commented Sep 2, 2024

$ gcc -nostdlib++ foo.c
gcc: error: unrecognized command-line option ‘-nostdlib++’
$ gcc --version
gcc (Gentoo 14.2.1_p20240817 p4) 14.2.1 20240817
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

That’s odd, I see the same behavior as before, with gcc (Ubuntu 14.2.0-4ubuntu1) 14.2.0:

$ gcc -nostdlib++ test.c
$ gcc --version
gcc (Ubuntu 14.2.0-4ubuntu1) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I wonder which one has downstream patches that affects this behavior…

@mgorny
Copy link
Member Author

mgorny commented Sep 2, 2024

Ok, I've put the brightest minds of Gentoo at it and we have an answer: it's supposed to fail but due to a bug in GCC, it doesn't fail if GCC was built with Ada support enabled.

@Chrismarsh
Copy link

Do I understand correctly that:

It = gcc -nostdlib++ foo.c

Should always fail, but if gcc was built with ada support, gcc doesn't fail. And thus, the llvm logic assuming this gcc flag doesn't fail is incorrect, leading to the issues?

@mstorsjo
Copy link
Member

mstorsjo commented Sep 2, 2024

Ok, I've put the brightest minds of Gentoo at it and we have an answer: it's supposed to fail but due to a bug in GCC, it doesn't fail if GCC was built with Ada support enabled.

Wow, that’s unexpected - but I somehow can see how that can happen. Thanks, that explains it - and explains why the fallout from this isn’t bigger.

Do I understand correctly that:

It = gcc -nostdlib++ foo.c

Should always fail, but if gcc was built with ada support, gcc doesn't fail. And thus, the llvm logic assuming this gcc flag doesn't fail is incorrect, leading to the issues?

Yes, there’s no ambiguity about that - we shouldn’t pass it in those contexts. The tricky part is that if the c++ driver does support it, we do want to pass it for all c++ test compilations. The problem is that CMAKE_REQUIRED_FLAGS doesn’t distinguish between which language mode is used for the compile/link tests; there’s no CMAKE_CXX_REQUIRED_FLAGS or similar.

I’ll see if I can come up with some way of working around this…

@petrhosek
Copy link
Member

There's a potential solution which is a part of a direction I'd like to explore but it's going to require some significant changes.

In CMake, you can query whether you're in the "try" mode by using:

get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)

This then lets you do things like:

if(IS_IN_TRY_COMPILE)
  set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib++")
 endif()

This would ideally be set in a toolchain file replacing the existing logic such as https://github.com/llvm/llvm-project/blob/llvmorg-19-init/runtimes/CMakeLists.txt#L138-L149.

The problem is that we currently don't use a toolchain file for the runtimes build, but I think we should. That would require refactoring the following function to generate a toolchain file which is a non-trivial task:

function(llvm_ExternalProject_Add name source_dir)
cmake_parse_arguments(ARG
"USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL;ALWAYS_CLEAN"
"SOURCE_DIR;FOLDER"
"CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS;PASSTHROUGH_PREFIXES;STRIP_TOOL;TARGET_TRIPLE"
${ARGN})
canonicalize_tool_name(${name} nameCanon)
foreach(arg ${ARG_CMAKE_ARGS})
if(arg MATCHES "^-DCMAKE_SYSTEM_NAME=")
string(REGEX REPLACE "^-DCMAKE_SYSTEM_NAME=(.*)$" "\\1" _cmake_system_name "${arg}")
endif()
endforeach()
# If CMAKE_SYSTEM_NAME is not set explicitly in the arguments passed to us,
# reflect CMake's own default.
if (NOT _cmake_system_name)
set(_cmake_system_name "${CMAKE_HOST_SYSTEM_NAME}")
endif()
if(NOT ARG_TARGET_TRIPLE)
set(target_triple ${LLVM_DEFAULT_TARGET_TRIPLE})
else()
set(target_triple ${ARG_TARGET_TRIPLE})
endif()
is_msvc_triple(is_msvc_target "${target_triple}")
if(NOT ARG_TOOLCHAIN_TOOLS)
set(ARG_TOOLCHAIN_TOOLS clang)
# AIX 64-bit XCOFF and big AR format is not yet supported in some of these tools.
if(NOT _cmake_system_name STREQUAL AIX)
list(APPEND ARG_TOOLCHAIN_TOOLS lld llvm-ar llvm-ranlib llvm-nm llvm-objdump)
if(_cmake_system_name STREQUAL Darwin)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-libtool-darwin llvm-lipo)
elseif(is_msvc_target)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-lib llvm-rc)
if (LLVM_ENABLE_LIBXML2)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-mt)
endif()
else()
# TODO: These tools don't fully support Mach-O format yet.
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-objcopy llvm-strip llvm-readelf)
endif()
endif()
endif()
foreach(tool ${ARG_TOOLCHAIN_TOOLS})
if(TARGET ${tool})
list(APPEND TOOLCHAIN_TOOLS ${tool})
# $<TARGET_FILE:tgt> only works on add_executable or add_library targets
# The below logic mirrors cmake's own implementation
get_target_property(target_type "${tool}" TYPE)
if(NOT target_type STREQUAL "OBJECT_LIBRARY" AND
NOT target_type STREQUAL "UTILITY" AND
NOT target_type STREQUAL "GLOBAL_TARGET" AND
NOT target_type STREQUAL "INTERFACE_LIBRARY")
list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:${tool}>)
endif()
endif()
endforeach()
if(NOT ARG_RUNTIME_LIBRARIES)
set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx)
endif()
foreach(lib ${ARG_RUNTIME_LIBRARIES})
if(TARGET ${lib})
list(APPEND RUNTIME_LIBRARIES ${lib})
endif()
endforeach()
if(ARG_ALWAYS_CLEAN)
set(always_clean clean)
endif()
if(clang IN_LIST TOOLCHAIN_TOOLS)
set(CLANG_IN_TOOLCHAIN On)
endif()
if(RUNTIME_LIBRARIES AND CLANG_IN_TOOLCHAIN)
list(APPEND TOOLCHAIN_BINS ${RUNTIME_LIBRARIES})
endif()
set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-stamps/)
set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-bins/)
add_custom_target(${name}-clear
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
COMMENT "Clobbering ${name} build and stamp directories"
USES_TERMINAL
)
if (ARG_FOLDER)
set_target_properties(${name}-clear PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
# Find all variables that start with a prefix and propagate them through
get_cmake_property(variableNames VARIABLES)
list(APPEND ARG_PASSTHROUGH_PREFIXES ${nameCanon})
foreach(prefix ${ARG_PASSTHROUGH_PREFIXES})
foreach(variableName ${variableNames})
if(variableName MATCHES "^${prefix}")
string(REPLACE ";" "|" value "${${variableName}}")
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
endif()
endforeach()
endforeach()
# Populate the non-project-specific passthrough variables
foreach(variableName ${LLVM_EXTERNAL_PROJECT_PASSTHROUGH})
if(DEFINED ${variableName})
if("${${variableName}}" STREQUAL "")
set(value "")
else()
string(REPLACE ";" "|" value "${${variableName}}")
endif()
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
endif()
endforeach()
if(ARG_USE_TOOLCHAIN AND NOT CMAKE_CROSSCOMPILING)
if(CLANG_IN_TOOLCHAIN)
if(is_msvc_target)
set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
else()
set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(lld IN_LIST TOOLCHAIN_TOOLS)
if(is_msvc_target)
list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX})
elseif(NOT _cmake_system_name STREQUAL Darwin)
list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/ld.lld${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(llvm-ar IN_LIST TOOLCHAIN_TOOLS)
if(is_msvc_target)
list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lib${CMAKE_EXECUTABLE_SUFFIX})
else()
list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(llvm-libtool-darwin IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_LIBTOOL=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-libtool-darwin${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-lipo IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_LIPO=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lipo${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-ranlib IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-nm IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_NM=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-nm${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-objdump IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_OBJDUMP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objdump${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-objcopy IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_OBJCOPY=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objcopy${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-strip IN_LIST TOOLCHAIN_TOOLS AND NOT ARG_STRIP_TOOL)
list(APPEND compiler_args -DCMAKE_STRIP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-strip${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-readelf IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_READELF=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-readelf${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-mt IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
list(APPEND compiler_args -DCMAKE_MT=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-mt${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-rc IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
list(APPEND compiler_args -DCMAKE_RC_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-rc${CMAKE_EXECUTABLE_SUFFIX})
endif()
list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
# Add LLVMgold.so dependency if it is available, as clang may need it for
# LTO.
if(CLANG_IN_TOOLCHAIN AND TARGET LLVMgold)
list(APPEND ARG_DEPENDS LLVMgold)
endif()
endif()
if(ARG_STRIP_TOOL)
list(APPEND compiler_args -DCMAKE_STRIP=${ARG_STRIP_TOOL})
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
DEPENDS ${ARG_DEPENDS}
COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
COMMENT "Clobbering bootstrap build and stamp directories"
)
add_custom_target(${name}-clobber
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
if (ARG_FOLDER)
set_target_properties(${name}-clobber PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
if(ARG_EXCLUDE_FROM_ALL)
set(exclude EXCLUDE_FROM_ALL 1)
endif()
if(CMAKE_SYSROOT)
set(sysroot_arg -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
endif()
if(CMAKE_CROSSCOMPILING)
set(compiler_args -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_LINKER=${CMAKE_LINKER}
-DCMAKE_AR=${CMAKE_AR}
-DCMAKE_RANLIB=${CMAKE_RANLIB}
-DCMAKE_NM=${CMAKE_NM}
-DCMAKE_OBJCOPY=${CMAKE_OBJCOPY}
-DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}
-DCMAKE_STRIP=${CMAKE_STRIP}
-DCMAKE_READELF=${CMAKE_READELF})
set(llvm_config_path ${LLVM_CONFIG_PATH})
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR
${PACKAGE_VERSION})
if(DEFINED CLANG_RESOURCE_DIR AND NOT CLANG_RESOURCE_DIR STREQUAL "")
set(resource_dir ${LLVM_TOOLS_BINARY_DIR}/${CLANG_RESOURCE_DIR})
else()
set(resource_dir "${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION_MAJOR}")
endif()
set(flag_types ASM C CXX MODULE_LINKER SHARED_LINKER EXE_LINKER)
foreach(type ${flag_types})
set(${type}_flag -DCMAKE_${type}_FLAGS_INIT=-resource-dir=${resource_dir})
endforeach()
string(REPLACE ";" "|" flag_string "${flag_types}")
foreach(arg ${ARG_CMAKE_ARGS})
if(arg MATCHES "^-DCMAKE_(${flag_string})_FLAGS")
foreach(type ${flag_types})
if(arg MATCHES "^-DCMAKE_${type}_FLAGS")
string(REGEX REPLACE "^-DCMAKE_${type}_FLAGS=(.*)$" "\\1" flag_value "${arg}")
set(${type}_flag "${${type}_flag} ${flag_value}")
endif()
endforeach()
else()
list(APPEND cmake_args ${arg})
endif()
endforeach()
foreach(type ${flag_types})
list(APPEND cmake_args ${${type}_flag})
endforeach()
else()
set(cmake_args ${ARG_CMAKE_ARGS})
endif()
else()
set(llvm_config_path "$<TARGET_FILE:llvm-config>")
set(cmake_args ${ARG_CMAKE_ARGS})
endif()
if(ARG_TARGET_TRIPLE)
list(APPEND compiler_args -DCMAKE_C_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_CXX_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_ASM_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
endif()
if(CMAKE_VERBOSE_MAKEFILE)
set(verbose -DCMAKE_VERBOSE_MAKEFILE=ON)
endif()
ExternalProject_Add(${name}
DEPENDS ${ARG_DEPENDS} llvm-config
${name}-clobber
PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
SOURCE_DIR ${source_dir}
STAMP_DIR ${STAMP_DIR}
BINARY_DIR ${BINARY_DIR}
${exclude}
CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
--no-warn-unused-cli
${compiler_args}
${verbose}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
${sysroot_arg}
-DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
-DLLVM_CONFIG_PATH=${llvm_config_path}
-DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
-DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
-DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
-DLLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO=${LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO}
-DLLVM_USE_RELATIVE_PATHS_IN_FILES=${LLVM_USE_RELATIVE_PATHS_IN_FILES}
-DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
-DLLVM_SOURCE_PREFIX=${LLVM_SOURCE_PREFIX}
-DPACKAGE_VERSION=${PACKAGE_VERSION}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
-DCMAKE_EXPORT_COMPILE_COMMANDS=1
${cmake_args}
${PASSTHROUGH_VARIABLES}
INSTALL_COMMAND ""
STEP_TARGETS configure build
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LIST_SEPARATOR |
)
if (ARG_FOLDER)
set_target_properties(
${name} ${name}-clobber ${name}-build ${name}-configure
PROPERTIES FOLDER "${ARG_FOLDER}"
)
endif ()
if(ARG_USE_TOOLCHAIN)
set(force_deps DEPENDS ${TOOLCHAIN_BINS})
endif()
llvm_ExternalProject_BuildCmd(run_clean clean ${BINARY_DIR})
ExternalProject_Add_Step(${name} clean
COMMAND ${run_clean}
COMMENT "Cleaning ${name}..."
DEPENDEES configure
${force_deps}
WORKING_DIRECTORY ${BINARY_DIR}
EXCLUDE_FROM_MAIN 1
USES_TERMINAL 1
)
ExternalProject_Add_StepTargets(${name} clean)
if (ARG_FOLDER)
set_target_properties(${name}-clean PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
if(ARG_USE_TOOLCHAIN)
add_dependencies(${name}-clean ${name}-clobber)
set_target_properties(${name}-clean PROPERTIES
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
endif()
if(NOT ARG_NO_INSTALL)
install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_DO_STRIP=\${CMAKE_INSTALL_DO_STRIP} -P ${BINARY_DIR}/cmake_install.cmake\)"
COMPONENT ${name})
add_llvm_install_targets(install-${name}
DEPENDS ${name}
COMPONENT ${name})
if (ARG_FOLDER)
set_target_properties(install-${name} PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
endif()
# Add top-level targets
foreach(target ${ARG_EXTRA_TARGETS})
if(DEFINED ${target})
set(external_target "${${target}}")
else()
set(external_target "${target}")
endif()
llvm_ExternalProject_BuildCmd(build_runtime_cmd ${external_target} ${BINARY_DIR})
add_custom_target(${target}
COMMAND ${build_runtime_cmd}
DEPENDS ${name}-configure
WORKING_DIRECTORY ${BINARY_DIR}
VERBATIM
USES_TERMINAL)
if (ARG_FOLDER)
set_target_properties(${target} PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
endforeach()
endfunction()

@mstorsjo
Copy link
Member

mstorsjo commented Sep 3, 2024

There's a potential solution which is a part of a direction I'd like to explore but it's going to require some significant changes.

In CMake, you can query whether you're in the "try" mode by using:

get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)

This then lets you do things like:

if(IS_IN_TRY_COMPILE)
  set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib++")
 endif()

This would ideally be set in a toolchain file replacing the existing logic such as https://github.com/llvm/llvm-project/blob/llvmorg-19-init/runtimes/CMakeLists.txt#L138-L149.

The problem is that we currently don't use a toolchain file for the runtimes build, but I think we should. That would require refactoring the following function to generate a toolchain file which is a non-trivial task:

function(llvm_ExternalProject_Add name source_dir)
cmake_parse_arguments(ARG
"USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL;ALWAYS_CLEAN"
"SOURCE_DIR;FOLDER"
"CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS;PASSTHROUGH_PREFIXES;STRIP_TOOL;TARGET_TRIPLE"
${ARGN})
canonicalize_tool_name(${name} nameCanon)
foreach(arg ${ARG_CMAKE_ARGS})
if(arg MATCHES "^-DCMAKE_SYSTEM_NAME=")
string(REGEX REPLACE "^-DCMAKE_SYSTEM_NAME=(.*)$" "\\1" _cmake_system_name "${arg}")
endif()
endforeach()
# If CMAKE_SYSTEM_NAME is not set explicitly in the arguments passed to us,
# reflect CMake's own default.
if (NOT _cmake_system_name)
set(_cmake_system_name "${CMAKE_HOST_SYSTEM_NAME}")
endif()
if(NOT ARG_TARGET_TRIPLE)
set(target_triple ${LLVM_DEFAULT_TARGET_TRIPLE})
else()
set(target_triple ${ARG_TARGET_TRIPLE})
endif()
is_msvc_triple(is_msvc_target "${target_triple}")
if(NOT ARG_TOOLCHAIN_TOOLS)
set(ARG_TOOLCHAIN_TOOLS clang)
# AIX 64-bit XCOFF and big AR format is not yet supported in some of these tools.
if(NOT _cmake_system_name STREQUAL AIX)
list(APPEND ARG_TOOLCHAIN_TOOLS lld llvm-ar llvm-ranlib llvm-nm llvm-objdump)
if(_cmake_system_name STREQUAL Darwin)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-libtool-darwin llvm-lipo)
elseif(is_msvc_target)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-lib llvm-rc)
if (LLVM_ENABLE_LIBXML2)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-mt)
endif()
else()
# TODO: These tools don't fully support Mach-O format yet.
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-objcopy llvm-strip llvm-readelf)
endif()
endif()
endif()
foreach(tool ${ARG_TOOLCHAIN_TOOLS})
if(TARGET ${tool})
list(APPEND TOOLCHAIN_TOOLS ${tool})
# $<TARGET_FILE:tgt> only works on add_executable or add_library targets
# The below logic mirrors cmake's own implementation
get_target_property(target_type "${tool}" TYPE)
if(NOT target_type STREQUAL "OBJECT_LIBRARY" AND
NOT target_type STREQUAL "UTILITY" AND
NOT target_type STREQUAL "GLOBAL_TARGET" AND
NOT target_type STREQUAL "INTERFACE_LIBRARY")
list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:${tool}>)
endif()
endif()
endforeach()
if(NOT ARG_RUNTIME_LIBRARIES)
set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx)
endif()
foreach(lib ${ARG_RUNTIME_LIBRARIES})
if(TARGET ${lib})
list(APPEND RUNTIME_LIBRARIES ${lib})
endif()
endforeach()
if(ARG_ALWAYS_CLEAN)
set(always_clean clean)
endif()
if(clang IN_LIST TOOLCHAIN_TOOLS)
set(CLANG_IN_TOOLCHAIN On)
endif()
if(RUNTIME_LIBRARIES AND CLANG_IN_TOOLCHAIN)
list(APPEND TOOLCHAIN_BINS ${RUNTIME_LIBRARIES})
endif()
set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-stamps/)
set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${name}-bins/)
add_custom_target(${name}-clear
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
COMMENT "Clobbering ${name} build and stamp directories"
USES_TERMINAL
)
if (ARG_FOLDER)
set_target_properties(${name}-clear PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
# Find all variables that start with a prefix and propagate them through
get_cmake_property(variableNames VARIABLES)
list(APPEND ARG_PASSTHROUGH_PREFIXES ${nameCanon})
foreach(prefix ${ARG_PASSTHROUGH_PREFIXES})
foreach(variableName ${variableNames})
if(variableName MATCHES "^${prefix}")
string(REPLACE ";" "|" value "${${variableName}}")
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
endif()
endforeach()
endforeach()
# Populate the non-project-specific passthrough variables
foreach(variableName ${LLVM_EXTERNAL_PROJECT_PASSTHROUGH})
if(DEFINED ${variableName})
if("${${variableName}}" STREQUAL "")
set(value "")
else()
string(REPLACE ";" "|" value "${${variableName}}")
endif()
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
endif()
endforeach()
if(ARG_USE_TOOLCHAIN AND NOT CMAKE_CROSSCOMPILING)
if(CLANG_IN_TOOLCHAIN)
if(is_msvc_target)
set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
else()
set(compiler_args -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(lld IN_LIST TOOLCHAIN_TOOLS)
if(is_msvc_target)
list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX})
elseif(NOT _cmake_system_name STREQUAL Darwin)
list(APPEND compiler_args -DCMAKE_LINKER=${LLVM_RUNTIME_OUTPUT_INTDIR}/ld.lld${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(llvm-ar IN_LIST TOOLCHAIN_TOOLS)
if(is_msvc_target)
list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lib${CMAKE_EXECUTABLE_SUFFIX})
else()
list(APPEND compiler_args -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar${CMAKE_EXECUTABLE_SUFFIX})
endif()
endif()
if(llvm-libtool-darwin IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_LIBTOOL=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-libtool-darwin${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-lipo IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_LIPO=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lipo${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-ranlib IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-nm IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_NM=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-nm${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-objdump IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_OBJDUMP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objdump${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-objcopy IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_OBJCOPY=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objcopy${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-strip IN_LIST TOOLCHAIN_TOOLS AND NOT ARG_STRIP_TOOL)
list(APPEND compiler_args -DCMAKE_STRIP=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-strip${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-readelf IN_LIST TOOLCHAIN_TOOLS)
list(APPEND compiler_args -DCMAKE_READELF=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-readelf${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-mt IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
list(APPEND compiler_args -DCMAKE_MT=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-mt${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(llvm-rc IN_LIST TOOLCHAIN_TOOLS AND is_msvc_target)
list(APPEND compiler_args -DCMAKE_RC_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-rc${CMAKE_EXECUTABLE_SUFFIX})
endif()
list(APPEND ARG_DEPENDS ${TOOLCHAIN_TOOLS})
# Add LLVMgold.so dependency if it is available, as clang may need it for
# LTO.
if(CLANG_IN_TOOLCHAIN AND TARGET LLVMgold)
list(APPEND ARG_DEPENDS LLVMgold)
endif()
endif()
if(ARG_STRIP_TOOL)
list(APPEND compiler_args -DCMAKE_STRIP=${ARG_STRIP_TOOL})
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
DEPENDS ${ARG_DEPENDS}
COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
COMMENT "Clobbering bootstrap build and stamp directories"
)
add_custom_target(${name}-clobber
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
if (ARG_FOLDER)
set_target_properties(${name}-clobber PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
if(ARG_EXCLUDE_FROM_ALL)
set(exclude EXCLUDE_FROM_ALL 1)
endif()
if(CMAKE_SYSROOT)
set(sysroot_arg -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
endif()
if(CMAKE_CROSSCOMPILING)
set(compiler_args -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_LINKER=${CMAKE_LINKER}
-DCMAKE_AR=${CMAKE_AR}
-DCMAKE_RANLIB=${CMAKE_RANLIB}
-DCMAKE_NM=${CMAKE_NM}
-DCMAKE_OBJCOPY=${CMAKE_OBJCOPY}
-DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}
-DCMAKE_STRIP=${CMAKE_STRIP}
-DCMAKE_READELF=${CMAKE_READELF})
set(llvm_config_path ${LLVM_CONFIG_PATH})
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR
${PACKAGE_VERSION})
if(DEFINED CLANG_RESOURCE_DIR AND NOT CLANG_RESOURCE_DIR STREQUAL "")
set(resource_dir ${LLVM_TOOLS_BINARY_DIR}/${CLANG_RESOURCE_DIR})
else()
set(resource_dir "${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION_MAJOR}")
endif()
set(flag_types ASM C CXX MODULE_LINKER SHARED_LINKER EXE_LINKER)
foreach(type ${flag_types})
set(${type}_flag -DCMAKE_${type}_FLAGS_INIT=-resource-dir=${resource_dir})
endforeach()
string(REPLACE ";" "|" flag_string "${flag_types}")
foreach(arg ${ARG_CMAKE_ARGS})
if(arg MATCHES "^-DCMAKE_(${flag_string})_FLAGS")
foreach(type ${flag_types})
if(arg MATCHES "^-DCMAKE_${type}_FLAGS")
string(REGEX REPLACE "^-DCMAKE_${type}_FLAGS=(.*)$" "\\1" flag_value "${arg}")
set(${type}_flag "${${type}_flag} ${flag_value}")
endif()
endforeach()
else()
list(APPEND cmake_args ${arg})
endif()
endforeach()
foreach(type ${flag_types})
list(APPEND cmake_args ${${type}_flag})
endforeach()
else()
set(cmake_args ${ARG_CMAKE_ARGS})
endif()
else()
set(llvm_config_path "$<TARGET_FILE:llvm-config>")
set(cmake_args ${ARG_CMAKE_ARGS})
endif()
if(ARG_TARGET_TRIPLE)
list(APPEND compiler_args -DCMAKE_C_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_CXX_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_ASM_COMPILER_TARGET=${ARG_TARGET_TRIPLE})
endif()
if(CMAKE_VERBOSE_MAKEFILE)
set(verbose -DCMAKE_VERBOSE_MAKEFILE=ON)
endif()
ExternalProject_Add(${name}
DEPENDS ${ARG_DEPENDS} llvm-config
${name}-clobber
PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
SOURCE_DIR ${source_dir}
STAMP_DIR ${STAMP_DIR}
BINARY_DIR ${BINARY_DIR}
${exclude}
CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
--no-warn-unused-cli
${compiler_args}
${verbose}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
${sysroot_arg}
-DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
-DLLVM_CONFIG_PATH=${llvm_config_path}
-DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
-DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
-DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
-DLLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO=${LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO}
-DLLVM_USE_RELATIVE_PATHS_IN_FILES=${LLVM_USE_RELATIVE_PATHS_IN_FILES}
-DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
-DLLVM_SOURCE_PREFIX=${LLVM_SOURCE_PREFIX}
-DPACKAGE_VERSION=${PACKAGE_VERSION}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
-DCMAKE_EXPORT_COMPILE_COMMANDS=1
${cmake_args}
${PASSTHROUGH_VARIABLES}
INSTALL_COMMAND ""
STEP_TARGETS configure build
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LIST_SEPARATOR |
)
if (ARG_FOLDER)
set_target_properties(
${name} ${name}-clobber ${name}-build ${name}-configure
PROPERTIES FOLDER "${ARG_FOLDER}"
)
endif ()
if(ARG_USE_TOOLCHAIN)
set(force_deps DEPENDS ${TOOLCHAIN_BINS})
endif()
llvm_ExternalProject_BuildCmd(run_clean clean ${BINARY_DIR})
ExternalProject_Add_Step(${name} clean
COMMAND ${run_clean}
COMMENT "Cleaning ${name}..."
DEPENDEES configure
${force_deps}
WORKING_DIRECTORY ${BINARY_DIR}
EXCLUDE_FROM_MAIN 1
USES_TERMINAL 1
)
ExternalProject_Add_StepTargets(${name} clean)
if (ARG_FOLDER)
set_target_properties(${name}-clean PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
if(ARG_USE_TOOLCHAIN)
add_dependencies(${name}-clean ${name}-clobber)
set_target_properties(${name}-clean PROPERTIES
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
endif()
if(NOT ARG_NO_INSTALL)
install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_DO_STRIP=\${CMAKE_INSTALL_DO_STRIP} -P ${BINARY_DIR}/cmake_install.cmake\)"
COMPONENT ${name})
add_llvm_install_targets(install-${name}
DEPENDS ${name}
COMPONENT ${name})
if (ARG_FOLDER)
set_target_properties(install-${name} PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
endif()
# Add top-level targets
foreach(target ${ARG_EXTRA_TARGETS})
if(DEFINED ${target})
set(external_target "${${target}}")
else()
set(external_target "${target}")
endif()
llvm_ExternalProject_BuildCmd(build_runtime_cmd ${external_target} ${BINARY_DIR})
add_custom_target(${target}
COMMAND ${build_runtime_cmd}
DEPENDS ${name}-configure
WORKING_DIRECTORY ${BINARY_DIR}
VERBATIM
USES_TERMINAL)
if (ARG_FOLDER)
set_target_properties(${target} PROPERTIES FOLDER "${ARG_FOLDER}")
endif ()
endforeach()
endfunction()

Interesting idea! Another complication with that, is that we don't only build runtimes via llvm-project/llvm/runtimes, but people can also build runtimes (in bootstrap/from-scratch scenarios) by directly building the llvm-project/runtimes directory. When doing that, it's somewhat expected that you need to set flags like -DCMAKE_C_COMPILER_WORKS=TRUE - but if such builds now would require using a custom specific toolchain file, that's a change that would affect quite a lot of potential builds around all downstreams.

@mstorsjo
Copy link
Member

mstorsjo commented Sep 3, 2024

CC @mstorsjo as the one who added the logic

FWIW, just for history for how these flags were added, I've just refactored it a little bit. A bit essential history for how these flags were added is in b688c58 (which just unconditionally added -nostdinc++ -nostdlib++), 98c89cc which added a rudimentary condition around them, and 125e8ef which added actual compiler checks to see whether the flags are supported.


On one hand, I'm a little undecided on whether it really makes sense to forcibly try to add these flags in the toplevel llvm-project/runtimes directory - it may make sense for libunwind/libcxxabi/libcxx, but other runtimes (like openmp) may e.g. require you to have a working C++ standard library already. And the Flang runtime is also (possibly, at some point) being moved to be built via the same mechanism, and whether these flags make sense there is also a bit unclear.


Just removing the checks in llvm-project/runtimes/CMakeLists.txt, https://github.com/llvm/llvm-project/blob/llvmorg-20-init/runtimes/CMakeLists.txt#L142-L153, probably fixes the OpenMP case.

But the case in libcxx, reported by @h-vetinari in #90332 (comment), wouldn't be fixed by that. Because libunwind/libcxxabi/libcxx also separately add these flags in https://github.com/llvm/llvm-project/blob/llvmorg-20-init/libcxx/cmake/config-ix.cmake#L42-L50, https://github.com/llvm/llvm-project/blob/llvmorg-20-init/libcxxabi/cmake/config-ix.cmake#L26-L34 and https://github.com/llvm/llvm-project/blob/llvmorg-20-init/libunwind/cmake/config-ix.cmake#L38-L46.
(This is probably something that was meant to be refactored into relying on the toplevel llvm-project/runtimes/CMakeLists.txt umbrella, but which has been missed so far. But as mentioned above, this does make me a little less certain that we really should be flat out assuming that all runtimes want this.)

Within the projects libunwind/libcxxabi/libcxx, which have fallbacks to -nodefaultlibs if -nostdlib++ is unsupported, we can just try to make sure we don't use -nostdlib++ if it isn't supported by the C driver. That should be fairly straightforward - but on the other hand probably takes us a bit in the wrong direction; ideally we'd be using -nostdlib++ everywhere and get rid of the -nodefaultlibs fallback codepath.

Just for testing, can @mgorny and @h-vetinari test if mstorsjo@runtimes-nostdlibxx fixes their issues?

@Chrismarsh
Copy link

@mstorsjo I am interesting in trying this patch. What version of llvm should I be applying this patch to? It is failing on llvm
17.0.06 (which might be expected)

mstorsjo added a commit to mstorsjo/llvm-project that referenced this issue Sep 4, 2024
If they are detected, we add them to CMAKE_REQUIRED_FLAGS. All flags
in that variable are used both when testing compilation of C and C++
(and for detecting libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do
support the -nostdlib++ option, but it's only supported by the
C++ compiler driver, not the C driver. (However, many builds of
GCC also do accept the option with the C driver, if GCC was
compiled with Ada support enabled, see [1]. That's why this
issue isn't noticed in all configurations with GCC.)

[1] llvm#90332 (comment)
@mstorsjo
Copy link
Member

mstorsjo commented Sep 4, 2024

@mstorsjo I am interesting in trying this patch. What version of llvm should I be applying this patch to? It is failing on llvm 17.0.06 (which might be expected)

Yeah it probably doesn't apply there. The patch itself is made against current git main. I tried applying it on 17.0.6 and fixing the conflicts: mstorsjo@runtimes-nostdlibxx-17

@h-vetinari
Copy link
Contributor

Your patch cherry-picks cleanly to 18.1.8, and I've tested in conda-forge/libcxx-feedstock#194 that it works - thanks a lot! 🙏

@h-vetinari
Copy link
Contributor

@mstorsjo, are you planning to open a PR with mstorsjo@runtimes-nostdlibxx?

mstorsjo added a commit to mstorsjo/llvm-project that referenced this issue Sep 12, 2024
While these flags semantically are relevant only for C++, we do
add them to CMAKE_REQUIRED_FLAGS if they are detected. All flags
in that variable are used both when testing compilation of C and C++
(and for detecting libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do
support the -nostdlib++ option, but it's only supported by the
C++ compiler driver, not the C driver. (However, many builds of
GCC also do accept the option with the C driver, if GCC was
compiled with Ada support enabled, see [1]. That's why this
issue isn't noticed in all configurations with GCC.)

Clang does support these options in both C and C++ driver modes.

[1] llvm#90332 (comment)
@mstorsjo
Copy link
Member

@mstorsjo, are you planning to open a PR with mstorsjo@runtimes-nostdlibxx?

Sure, done in #108357. It's probably not the best solution, but it should at least fix most of the issue with a pretty low effort.

sys-ceuplift pushed a commit to nstester/llvm-project that referenced this issue Oct 24, 2024
…lvm#108357)

While these flags semantically are relevant only for C++, we do add them
to CMAKE_REQUIRED_FLAGS if they are detected. All flags in that variable
are used both when testing compilation of C and C++ (and for detecting
libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do support
the -nostdlib++ option, but it's only supported by the C++ compiler
driver, not the C driver. (However, many builds of GCC also do accept
the option with the C driver, if GCC was compiled with Ada support
enabled, see [1]. That's why this issue isn't noticed in all
configurations with GCC.)

Clang does support these options in both C and C++ driver modes.

This should fix llvm#90332.

[1]
llvm#90332 (comment)
@petrhosek
Copy link
Member

Something I noticed:

check_include_file(hwloc.h LIBOMP_HAVE_HWLOC_H)
uses check_include_file but I think it should be using check_include_file_cxx since the openmp runtime is implemented in C++ in which case we wouldn't hit the issue with -nostdlib++ and -nostdinc++.

@mstorsjo
Copy link
Member

Something I noticed:

check_include_file(hwloc.h LIBOMP_HAVE_HWLOC_H)

uses check_include_file but I think it should be using check_include_file_cxx since the openmp runtime is implemented in C++ in which case we wouldn't hit the issue with -nostdlib++ and -nostdinc++.

That might help there, but when libcxxabi uses check_library_exists, e.g. here, we also have the same issue:

https://github.com/llvm/llvm-project/blob/llvmorg-19.1.2/libcxxabi/cmake/config-ix.cmake#L109

NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this issue Nov 4, 2024
…lvm#108357)

While these flags semantically are relevant only for C++, we do add them
to CMAKE_REQUIRED_FLAGS if they are detected. All flags in that variable
are used both when testing compilation of C and C++ (and for detecting
libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do support
the -nostdlib++ option, but it's only supported by the C++ compiler
driver, not the C driver. (However, many builds of GCC also do accept
the option with the C driver, if GCC was compiled with Ada support
enabled, see [1]. That's why this issue isn't noticed in all
configurations with GCC.)

Clang does support these options in both C and C++ driver modes.

This should fix llvm#90332.

[1]
llvm#90332 (comment)
@h-vetinari
Copy link
Contributor

Can we please reopen this issue until #108357 relands?

h-vetinari pushed a commit to h-vetinari/llvm-project that referenced this issue Nov 10, 2024
If they are detected, we add them to CMAKE_REQUIRED_FLAGS. All flags
in that variable are used both when testing compilation of C and C++
(and for detecting libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do
support the -nostdlib++ option, but it's only supported by the
C++ compiler driver, not the C driver. (However, many builds of
GCC also do accept the option with the C driver, if GCC was
compiled with Ada support enabled, see [1]. That's why this
issue isn't noticed in all configurations with GCC.)

[1] llvm#90332 (comment)
@EugeneZelenko EugeneZelenko reopened this Nov 10, 2024
h-vetinari pushed a commit to h-vetinari/llvm-project that referenced this issue Dec 24, 2024
…lvm#108357)

While these flags semantically are relevant only for C++, we do add them
to CMAKE_REQUIRED_FLAGS if they are detected. All flags in that variable
are used both when testing compilation of C and C++ (and for detecting
libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do support
the -nostdlib++ option, but it's only supported by the C++ compiler
driver, not the C driver. (However, many builds of GCC also do accept
the option with the C driver, if GCC was compiled with Ada support
enabled, see [1]. That's why this issue isn't noticed in all
configurations with GCC.)

Clang does support these options in both C and C++ driver modes.

This should fix llvm#90332.

[1]
llvm#90332 (comment)
oneseer pushed a commit to oneseer/libunwind that referenced this issue Mar 26, 2025
…(#108357)

While these flags semantically are relevant only for C++, we do add them
to CMAKE_REQUIRED_FLAGS if they are detected. All flags in that variable
are used both when testing compilation of C and C++ (and for detecting
libraries, which uses the C compiler driver).

Therefore, to be sure we safely can add the flags to
CMAKE_REQUIRED_FLAGS, test for the option with the C language.

This should fix compilation with GCC; newer versions of GCC do support
the -nostdlib++ option, but it's only supported by the C++ compiler
driver, not the C driver. (However, many builds of GCC also do accept
the option with the C driver, if GCC was compiled with Ada support
enabled, see [1]. That's why this issue isn't noticed in all
configurations with GCC.)

Clang does support these options in both C and C++ driver modes.

This should fix #90332.

[1]
llvm/llvm-project#90332 (comment)

NOKEYCHECK=True
GitOrigin-RevId: 75d0281bc81f0040c24d15bdf9c5cc46e9237224
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cmake Build system in general and CMake in particular openmp
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants