find_package doesn't look in default suffixes until enabling a language

Hi, I’ve got a bit of an unusual problem.

I have a package that ships a C++ compiler wrapper. And it’s not one of those cheesy compiler wrappers that is just used because nobody knows how packaging works. It’s actually pretty essential because it works around issues with the underlying compiler’s CLI. It’s essential that CMake sees this wrapper as the C++ compiler, and not the underlying compiler.

However, I don’t want developers to have to know this compiler wrapper exists - it’s essentially a hack, and it doesn’t make sense to make my developers think about it.

Essentially, what I want is this:

cmake_minimum_required(VERSION 3.17)
project(proj LANGUAGES NONE)

find_package(Foo REQUIRED)

# FOO_* is set by FooConfig.cmake
if (FOO_NEEDS_WRAPPER)
    if (NOT HOST_COMPILER)
        # Swap out the "default" C++ compiler for the wrapper, and cache both the new and old compiler
        include(CheckLanguage)
        check_language(CXX)
        set(HOST_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING "Underlying compiler")

        set(CMAKE_CXX_COMPILER ${FOO_COMPILER} CACHE STRING "C++ compiler" FORCE)
    endif()

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --host_cc ${HOST_COMPILER}") 
endif()


enable_language(CXX)

Unfortunately, I’ve found that find_package doesn’t work right unless I enable a language. It will search only in CMAKE_PREFIX_PATH for FooConfig.cmake, but not in, for example, CMAKE_PREFIX_PATH/lib64/cmake/Foo. If I add enable_language(C) prior to the find_package(Foo REQUIRED) call, then everything works as expected, but I don’t love having to enable the C compiler just to get this to work. I do not want to add enable_language(CXX) because I don’t want CMake to set the compiler until I’ve patched it, nor do I want CMake to think it needs to reconfigure because it’s been changed after enabling the language.

Does anybody know what’s going on here and how I might remove the enable_language(C) call? It’s not the end of the world if I need to keep it, but removing it would be best.

Oh, wait, is this what I needed this whole time?! Pass argument directly to the compiler

EDIT: Playing around with CMAKE_CXX_COMPILER_LAUNCHER - this might solve my problem.

I should pay more attention to the Discourse. :slight_smile: CXX_COMPILER_LAUNCHER and RULE_LAUNCH_LINK solved my problem without having to mess around with CMAKE_CXX_COMPILER, and I can set them after I call enable_language(CXX). Perfect!

It might be better (in the long run) for CMake to actually understand this compiler and make the right command line from the beginning. Replacing CMAKE_CXX_COMPILER_LAUNCHER will replace things like user ccache or sccache settings (though I suspect that these don’t support the compiler in question anyways). Just for future note on anyone else writing wrappers and trying to interpose via find_package :slight_smile: .

1 Like

The specific compiler wrapper is nvcc_wrapper in Kokkos. The problem that it primarily solves is that nvcc doesn’t view itself as a C++ compiler, but only as a CUDA compiler, and so doesn’t present a C++ compiler CLI. However, the point of Kokkos is to make your C++ code portable.

You’d have to look into it to see if there’s some generality there that CMake could provide as a replacement for nvcc_wrapper. I have a feeling it’s not a general enough problem.

@robert.maynard would know better about this specific case.

The problem that it primarily solves is that nvcc doesn’t view itself as a C++ compiler, but only as a CUDA compiler

It does support being a C++ compiler, specifically that is what -x c++ does :slight_smile: .

and so doesn’t present a C++ compiler CLI

There is no official standard CLI for a C++ compiler. NVCC provides an interface that doesn’t map to either of the 2 primary CLI interfaces ( GCC && MSVC ) and that is the problem that this wrapper is trying to solve.

I understand why nvcc_wrapper was created and the problems it solved. But given the advancements both in the nvcc frontend and CMake’s support of the CUDA language I don’t see the need to generalize it.