conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.14k stars 970 forks source link

[bug] Conan 1.59 compilation stage for test_package fails (missing type) whereas it succeeds in conan2 #15640

Open MartyMcFlyInTheSky opened 7 months ago

MartyMcFlyInTheSky commented 7 months ago

Environment details

Steps to reproduce

I was testing my conanfile.py for upload to conancenter. The library I'm packaging has an include "utility.hpp" which contains the following statement

#ifdef __has_include
  #if __has_include(<source_location>)
    #include <source_location>

namespace lf::detail {
using source_location = std::source_location;
}  // namespace lf::detail

Now here's the strange thing: When I execute the following using conan2 it works:

conan create all/conanfile.py -pr:b=cpp20 -pr:h=cpp20

However, when I use conan 1.5 with the exact same command, it can't build the testpackage, complaining that:

/home//.conan/data//2.1.1///package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/-2.1.1//detail/utility.hpp:37:30: error: no type named 'source_location' in namespace 'std' using source_location = std::source_location;

Rest assured that the cpp20 profile is also the exact same (I copied it):

[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=20
compiler.libcxx=libc++
compiler.version=15
os=Linux

[conf]
tools.build:compiler_executables={"cpp": "/usr/bin/clang++-15", "c": "/usr/bin/clang-15"}

[buildenv]
CMAKE_EXPORT_COMPILE_COMMANDS=ON

so the only difference seems to be the conan version involved. Now why would it compile in conan2 but not in conan 1.5?

Logs

No response

memsharded commented 7 months ago

Hi @MartyMcFlyInTheSky

Thanks for your question.

The way the profile and the compiler.cppstd=20 affects the compilation depends a lot on the build system integrations like CMakeToolchain, and how it is used in the recipe, and also what is in the CMakeLists.txt or in the build scripts.

To understand better why it is not working it would be necessary to know the recipe and the build scripts, if you can please share them, so we can reproduce the issue, that would help.

MartyMcFlyInTheSky commented 7 months ago

Not a problem. Here's the recipe:

conanfile.py

from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import check_min_cppstd
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get
from conan.tools.scm import Version
import os

required_conan_version = ">=1.52.0"

class PackageConan(ConanFile):
    name = "somelib"
    version = "2.1.1" 
    description = "My description."
    license = "MPL-2.0"
    author = "Some Guy"
    url = "https://github.com/conan-io/conan-center-index"
    homepage = "https://github.com/SomeGuy/somelib"
    topics = ("libstuff")
    package_type = "header-library"
    settings = "os", "arch", "compiler", "build_type"

    no_copy_source = True

    @property
    def _min_cppstd(self):
        return 20

    @property
    def _compilers_minimum_version(self):
        return {
            "apple-clang": "12.0.0",
            "clang": "10",
            "gcc": "10",
            "msvc": "19.29",
            "Visual Studio": "16.10",
        }

    def layout(self):
        cmake_layout(self)

    def build_requirements(self):
        self.tool_requires("cmake/3.28.1")
        if (not self.conf.get("tools.build:skip_test", default=True, check_type=bool)):
            self.test_requires("catch2/3.5.1")

    def package_id(self):
        self.info.clear()

    def validate(self):
        if self.settings.compiler.get_safe("cppstd"):
            check_min_cppstd(self, self._min_cppstd)
        minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False)
        if minimum_version and Version(self.settings.compiler.version) < minimum_version:
            raise ConanInvalidConfiguration(
                f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support."
            )

    def source(self):
        get(self, **self.conan_data["sources"][self.version], strip_root=True)

    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()
        tc = CMakeToolchain(self)
        tc.cache_variables["CPM_USE_LOCAL_PACKAGES"] = True
        if (not self.conf.get("tools.build:skip_test", default=True, check_type=bool)):
            tc.cache_variables["somelib_DEVELOPER_MODE"] = True
            tc.cache_variables["BUILD_TESTING"] = True
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
        if (not self.conf.get("tools.build:skip_test", default=True, check_type=bool)):
            cmake.test()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def package_info(self):
        self.cpp_info.includedirs = ["include/somelib-2.1.1"]
        self.cpp_info.bindirs = []
        self.cpp_info.libdirs = []
        self.cpp_info.set_property("cmake_file_name", "somelib")
        self.cpp_info.set_property("cmake_target_name", "somelib::somelib")

        if self.settings.os in ["Linux", "FreeBSD"]:
            self.cpp_info.system_libs.extend(["pthread"])

And the build script.

Top level CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)

include(cmake/prelude.cmake)

project(
  somelib
  VERSION 2.1.1
  DESCRIPTION "Some library."
  HOMEPAGE_URL "https://github.com/SomeGuy/somelib"
  LANGUAGES CXX
)

include(cmake/project-is-top-level.cmake)
include(cmake/variables.cmake)

# ---- Dependencies ----
find_package(Threads REQUIRED)

# ---- Declare library ----
add_library(somelib_somelib INTERFACE)
add_library(somelib::somelib ALIAS somelib_somelib)

target_link_libraries(somelib_somelib INTERFACE Threads::Threads)

set_property(
  TARGET somelib_somelib PROPERTY
  EXPORT_NAME somelib
)

set(CMAKE_INSTALL_INCLUDEDIR "include/somelib-${PROJECT_VERSION}" CACHE PATH "")

target_include_directories(
  somelib_somelib ${warning_guard}
  INTERFACE
  "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
  "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)

target_compile_features(somelib_somelib INTERFACE cxx_std_20)

# ---- Install rules ----
if(NOT CMAKE_SKIP_INSTALL_RULES)
  include(cmake/install-rules.cmake)
endif()

# ---- Developer mode ----
if(NOT somelib_DEVELOPER_MODE)
  return()
elseif(NOT PROJECT_IS_TOP_LEVEL)
  message(
    AUTHOR_WARNING
    "Developer mode is intended for developers of somelib"
  )
endif()

include(cmake/dev-mode.cmake)
Nekto89 commented 7 months ago

have you tried moving row compiler.version=15 before row compiler.cppstd=20 in profile?

franramirez688 commented 7 months ago

Hi @MartyMcFlyInTheSky

I just tried libfork with your conanfile.py provided and GCC-11 instead, and it's working fine for Conan 1.59, 1.63, and 2.x. I had no problems with anything. Have you tried to compile it with GCC just in case? I could not reproduce the issue either in Linux or macOS.

UPDATED: I modified my profile to simulate something like yours:

[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++
compiler.version=11
os=Linux

[conf]
tools.build:compiler_executables={"cpp": "/usr/bin/g++", "c": "/usr/bin/gcc"}

[buildenv]
CMAKE_EXPORT_COMPILE_COMMANDS=ON
MartyMcFlyInTheSky commented 7 months ago

@Nekto89 Thanks for the tipp, tried it, but still the same error

@franramirez688 Tried that as well, also no success. I'll try to reproduce this on my windows in wsl, maybe I can further encircle the problem that way. Strange though that it worked for you?

Update: I also couldn't reproduce the problem on wsl ubuntu. Everything works also for conan 1.59 there. Somehow it seems I have messed up some settings I guess.

memsharded commented 2 weeks ago

Any update here @MartyMcFlyInTheSky? Did you manage to reproduce (or hopefully you managed to update to Conan2), may the issue be closed? Thanks.