conan-io / conan

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

[question] cmake.test() and -c tools.build:skip_test=False with Conan-2.x #13864

Closed maitrey closed 1 year ago

maitrey commented 1 year ago

What is your question?

Dear Conan Folks,

I can see that the structure of folders is different in conan cache .. when i build locally i see the export sources sources and sources in another folder and build and package in another folder .. When the build is running everything is run inside a t folder and this is cleaned up once the package is created . Also, the CMAKE_SOURCE_DIR , CMAKE_BINARY_DIR ; CMAKE_CURRENT_SOURCE_DIR and CMAKE__CURRENT_BINARY_DIR all point to everything insiide the t folder . Its not possible to debug as the compile_commands.json information after copying to b folder is having information that no longer exists.How can I disable that the t folder stays for debugging purposes ? I am using the command to build my packages locally: conan create . --user autosar--channel bringupconan2 -pr:b=default -pr:h=ndp -c tools.build:skip_test=False I am using add_test to run static code analysis. In my case, there is a python script that I call. But I donot see the Testing logs and also if I use BUILD_TESTING I cannot see which testing targets are built :( . If I use like this:

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

and in CMakeLists.txt:

 if (BUILD_TESTING)
add_test(testTarget ${PYTHONPATH} ${ENV_TESTTOOL}/staticcodeanalysis_run.py )
endif()

It fails with: ERROR: mngr/0.0.0-dev.0@autosar/bringupconan2: Error in build() method, line 64 cmake.test() ConanException: Cannot wrap command with different envs,['C:\Users\.conan2\p\t\mngr396dd68d0350b\b\build\Debug\generators\conanbuild.bat'] - ['C:\Users\.conan2\p\t\mngr396dd68d0350b\b\build\Debug\generators\conanrun.sh']

If I use add_custom_target instead of add_test it fails with: ERROR: Couldn't move folder: C:\Users.conan2\p\t\mngr5fc49c520f875->C:\Users.conan2\p\mngrbe25c70a5cd31 Destination path C:\Users.conan2\p\mngrbe25c70a5cd31\mngr5fc49c520f875 already exists Folder might be busy or open. Close any app using it and retry. And there is no other application that has opened this location , unfortuantely. How do I fix it ?

Have you read the CONTRIBUTING guide?

memsharded commented 1 year ago

Hi @maitrey

ee that the structure of folders is different in conan cache .. when i build locally i see the export sources sources and sources in another folder and build and package in another folder .. When the build is running everything is run inside a t folder and this is cleaned up once the package is created . Also, the CMAKE_SOURCE_DIR , CMAKE_BINARY_DIR ; CMAKE_CURRENT_SOURCE_DIR and CMAKE__CURRENT_BINARY_DIR all point to everything insiide the t folder . Its not possible to debug as the compile_commands.json information after copying to b folder is having information that no longer exists.How can I disable that the t folder stays for debugging purposes ?

I don't think this is related to this ticket, but this would be a different question. There will be some changes in 2.0.5 (https://github.com/conan-io/conan/pull/13833) that will allow debugging and step-into into packages in the Conan cache. Still, I dont think this is related at all to the other things in this ticket.

memsharded commented 1 year ago

The implementation of cmake.test() contains:

  def test(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env=""):
        if self._conanfile.conf.get("tools.build:skip_test", check_type=bool):
            return

So you shouldn't need to add anything to your recipe, just cmake.test(), and it will be skipped conveniently if necessary.

memsharded commented 1 year ago

Finally, it would be necessary to have something to reproduce, with the information above is not possible to know what could be happening.

I'd recommend starting from the conan new cmake_lib -d name=pkg -d version=0.1 template, add there the minimum files and changes to reproduce the case, and put it in a .zip or in a Github repo and share with us, that would really help to know what is happening.

maitrey commented 1 year ago

I will try to upload the code later today. In conan-1.56, I did not have this issue with cmake.test(). I have always used build and tests but with 2.x, I wanted to take benefit of the feature skip tests. conan injects a variable BUILD_TESTING and I started to use that. I get a new error today:
cmake.test() ConanException: Cannot wrap command with different envs,['C:\Users.conan2\p\t\mngr00e175ed7cfac\b\build\Debug\generators\conanbuild.bat'] - ['C:\Users.conan2\p\t\mngr00e175ed7cfac\b\build\Debug\generators\conanrun.sh'] But this should not happen as: https://github.com/conan-io/conan/blob/2.0.4/conan/tools/env/environment.py#L530 My recipes look like this:

from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps

class Mngr(ConanFile):
    name = 'mngr'
    exports_sources = "src/*", "inc/*", "test/*" ,"CMakeLists.txt" , "conf/*", "report/*"
    settings =  "os", "compiler", "arch", "build_type"
    description = "Mngr manages the control unit"
    topics = "Production Software"
    python_requires = "common/1.0"
    python_requires_extend = "common.Base"

    def generate(self):
        #ms = VirtualBuildEnv(self)
        #ms.generate()
        tc = CMakeToolchain(self)
        tc.generate()
        deps = CMakeDeps(self)
        deps.generate()

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

    def package_info(self):
        self.cpp_info.includedirs = ['include']
        self.cpp_info.libdirs = ['lib']
        self.cpp_info.objects =  [os.path.join("lib", "mngr.dll")]

And common class contains code that is shared across all packages and has the following content :

from conan import ConanFile
from conan.tools.scm import Git
from conan.tools.cmake import CMake
from conan.tools.cmake import cmake_layout
from conan.tools.env import VirtualBuildEnv
from conan.tools.env import VirtualRunEnv
from conan.errors import ConanException
from conan.tools.files import load, update_conandata

class Base:
    #def export(self):
    #   git = Git(self, self.recipe_folder)
    #   scm_url, scm_commit = git.get_url_and_commit()
    #   update_conandata(self, {"sources": {"commit": scm_commit, "url": scm_url}})

    def layout(self):
        cmake_layout(self)

    def build(self): 
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

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

class Common(ConanFile):
    name = "common"
    version = "1.0"
    package_type = "python-require"
memsharded commented 1 year ago

A couple of quick comments:

The problem with the .sh and .bat files seems related to the configuration. If you can please share the whole output before that error, that could give us some hints.

maitrey commented 1 year ago

Thanks for the tips. Fixed it . In the build folder should I have both the : conanbuildenv-debug-ndp.bat and conanrunenv-debug-ndp.sh If I read this only one should exist in the cache. Another point I noticed is that the error:

cmake.test()
ConanException: Cannot wrap command with different envs,['C:\Users.conan2\p\t\mngr00e175ed7cfac\b\build\Debug\generators\conanbuild-ndp.bat'] - ['C:\Users.conan2\p\t\mngr00e175ed7cfac\b\build\Debug\generators\conanrun-ndp.sh']

Comes up only when I add cmake.test(). Does that give any hint to you? If I run it without cmake.test() I donot see the above error. I use this from command line , i donot see the above error : conan create . --user autosar --channel bringupconan2 -pr:b=default -pr:h=ndp -c tools.build:skip_test=False

memsharded commented 1 year ago

That could happen if it is some cross-building, this is why I was asking about the configuration and the full output. In that case, the cmake.test() probably cannot be run and should be protected with if can_run(self): cmake.test()? (There could be the discussion if this should already be done internally by cmake.test() too)

maitrey commented 1 year ago

Yes it is cross building. I am sorry but what does can_run(self) do ? How did it work with conan-1.x ? Has something changed with respect to cmake.test(). Sorry for the list of stupid questions.

maitrey commented 1 year ago

https://docs.conan.io/2/reference/conanfile/methods/test.html?highlight=can_run -> But here it says not to use it for any kind of testing : unit, integration or functional tests.

memsharded commented 1 year ago

Well, it seems that for cross-building scenarios tools.build:skip_test=True would be necessary to make sure test building is skipped?

maitrey commented 1 year ago

Okay that I understand will run the build but skip the tests. Question is then how to run the tests ?

memsharded commented 1 year ago

But you cannot run the tests if you are cross building. They will not run in the build machine. Am I missing something?

maitrey commented 1 year ago

I used cmake.test() with conan-1.59 and all tests could be executed (unit tests, functional tests.), It looks to me that there has been a change with 2.x and it doesnot work anymore. I understand that I cannot run the tests using cmake.test() anymore if i am doing cross building. Question is:

======== Exporting recipe to the cache ======== mngr/0.0.0-dev.0@autosar/bringup2: Exporting package recipe: C:\Projects\mngr\conanfile.py mngr/0.0.0-dev.0@autosar/bringup2: Copied 1 '.py' file: conanfile.py mngr/0.0.0-dev.0@autosar/bringup2: Copied 20 '.txt' files mngr/0.0.0-dev.0@autosar/bringup2: Copied 2 '.yaml' files: ci.yaml, qac.yaml mngr/0.0.0-dev.0@autosar/bringup2: Copied 1 '.sbsx' file: mngr.sbsx mngr/0.0.0-dev.0@autosar/bringup2: Copied 1 '.vsdx' file: mngr_Diagrams.vsdx mngr/0.0.0-dev.0@autosar/bringup2: Copied 1 '.arxml' file: mngr_If.arxml mngr/0.0.0-dev.0@autosar/bringup2: Copied 5 '.c' files mngr/0.0.0-dev.0@autosar/bringup2: Copied 1 '.h' file: mngr.h mngr/0.0.0-dev.0@autosar/bringup2: Copied 64 '.html' files mngr/0.0.0-dev.0@autosar/bringup2: Exported to cache folder: C:\Users\.conan2\p\mngrfeb51d86c0555\e mngr/0.0.0-dev.0@autosar/bringup2: Exported: mngr/0.0.0-dev.0@autosar/bringup2#52e6b96cc8cc69473a41baa392338a9c (2023-05-11 14:00:45 UTC)

======== Input profiles ======== Profile host: [settings] arch=NDP build_type=Debug compiler=gcc compiler.version=1.3 os=RTOS [conf] tools.cmake.cmaketoolchain:generator=MinGW Makefiles tools.build:skip_test=False [buildenv] PATH+=(path)D:/Tools/ndp/bin CTCHOME=D:/Tools/ctc/ctc9.0 CC=D:/Tools/ndp/bin/gcc.exe LD=D:/Tools/ndp/bin/gcc.exe AR=D:/Tools/ndp/bin/ar.exe AS=D:/Tools/ndp/bin/as RANLIB=D:/Tools/ndp/bin/ranlib STRIP=D:/Tools/ndp/bin/strip CFLAGS=-O2 CFLAGS_RELEASE=-O2 -g -W CFLAGS_DEBUG=-O2 -g -W -Wall LDFLAGS=-lgcc

Profile build: [settings] arch=x86_64 build_type=Debug compiler=msvc compiler.cppstd=14 compiler.runtime=dynamic compiler.runtime_type=Debug compiler.version=192 os=Windows [conf] tools.cmake.cmaketoolchain:generator=MinGW Makefiles

======== Computing dependency graph ======== Graph root cli Requirements saw/0.0.0-dev.0@autosar/bringup2#65588de03eadd383aac8ecbe2726c13b - Cache mngr/0.0.0-dev.0@autosar/bringup2#52e6b96cc8cc69473a41baa392338a9c - Cache Python requires autosarcommon/1.0#7737dc2589f8f9675db3129406b7a3e1 - Cache

======== Computing necessary packages ======== mngr/0.0.0-dev.0@autosar/bringup2: Forced build from source Requirements saw/0.0.0-dev.0@autosar/bringup2#65588de03eadd383aac8ecbe2726c13b:58d285fe75f972a49f0d668a8df9d770637789fd#a719b78df359a9365c530bd9ae8411c5 - Cache mngr/0.0.0-dev.0@autosar/bringup2#52e6b96cc8cc69473a41baa392338a9c:4f3746ba299109defe30499d78dfce631147fc5d - Build

======== Installing packages ======== saw/0.0.0-dev.0@autosar/bringup2: Already installed! (1 of 2)

-------- Installing package mngr/0.0.0-dev.0@autosar/bringup2 (2 of 2) -------- mngr/0.0.0-dev.0@autosar/bringup2: Building from source mngr/0.0.0-dev.0@autosar/bringup2: Package mngr/0.0.0-dev.0@autosar/bringup2:4f3746ba299109defe30499d78dfce631147fc5d mngr/0.0.0-dev.0@autosar/bringup2: Copying sources to build folder mngr/0.0.0-dev.0@autosar/bringup2: Building your package in C:\Users\.conan2\p\t\mngr6f49df387e9b7\b mngr/0.0.0-dev.0@autosar/bringup2: Calling generate() mngr/0.0.0-dev.0@autosar/bringup2: Generators folder: C:\Users\.conan2\p\t\mngr6f49df387e9b7\b\build\Debug\generators mngr/0.0.0-dev.0@autosar/bringup2: CMakeToolchain generated: conan_toolchain.cmake mngr/0.0.0-dev.0@autosar/bringup2: CMakeToolchain generated: CMakePresets.json mngr/0.0.0-dev.0@autosar/bringup2: CMakeToolchain generated: ......\CMakeUserPresets.json mngr/0.0.0-dev.0@autosar/bringup2: Generating aggregated env files mngr/0.0.0-dev.0@autosar/bringup2: Generated aggregated env files: ['conanbuild.bat', 'conanrun.sh'] mngr/0.0.0-dev.0@autosar/bringup2: Calling build() mngr/0.0.0-dev.0@autosar/bringup2: Running CMake.configure() mngr/0.0.0-dev.0@autosar/bringup2: RUN: cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE="C:/Users/.conan2/p/t/mngr6f49df387e9b7/b/build/Debug/generators/conan_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="C:/Users//.conan2/p/t/mngr6f49df387e9b7/p" -DCMAKE_SH="CMAKE_SH-NOTFOUND" -DCMAKE_POLICY_DEFAULT_CMP0091="NEW" -DCMAKE_BUILD_TYPE="Debug" "C:\Users\.conan2\p\t\mngr6f49df387e9b7\b." -- Using Conan toolchain: C:/Users//.conan2/p/t/mngr6f49df387e9b7/b/build/Debug/generators/conan_toolchain.cmake -- The C compiler identification is GNU 4.6.4 System is unknown to cmake, create: Platform/RTOS to use this system, please post your config file on discourse.cmake.org so it can be added to cmake -- Detecting C compiler ABI info System is unknown to cmake, create: Platform/RTOS to use this system, please post your config file on discourse.cmake.org so it can be added to cmake -- Detecting C compiler ABI info - done -- Check for working C compiler: D:/Tools/ndp/bin/gcc.exe - skipped -- Detecting C compile features System is unknown to cmake, create: Platform/RTOS to use this system, please post your config file on discourse.cmake.org so it can be added to cmake -- Detecting C compile features - done -- Conan: Target declared 'saw::saw' The location of CMAKE directories is:C:/Users//.conan2/p/t/mngr6f49df387e9b7/b,C:/Users//.conan2/p/t/mngr6f49df387e9b7/b/_src saw is found, proceeding to generate code and compile -- Configuring done -- Generating done CMake Warning: Manually-specified variables were not used by the project:

CMAKE_POLICY_DEFAULT_CMP0091
CMAKE_SH

-- Build files have been written to: C:/Users//.conan2/p/t/mngr6f49df387e9b7/b/build/Debug

mngr/0.0.0-dev.0@autosar/bringup2: Running CMake.build() mngr/0.0.0-dev.0@autosar/bringup2: RUN: cmake --build "C:\Users\.conan2\p\t\mngr6f49df387e9b7\b\build\Debug" -- -j8 [ 33%] Building C object _src/CMakeFiles/mngr.dir/mngr.c.obj [ 33%] Built target mngr [ 66%] Making reports directory [100%] Generate Test Frame Test frame generation completed. [100%] Built target tptTestframe

mngr/0.0.0-dev.0@autosar/bringup2: ERROR: Package '4f3746ba299109defe30499d78dfce631147fc5d' build failed mngr/0.0.0-dev.0@autosar/bringup2: WARN: Build folder C:\Users\.conan2\p\t\mngr6f49df387e9b7\b\build\Debug


Recipe 'mngr/0.0.0-dev.0@autosar/bringup2' cannot build its binary It is possible that this recipe is not Conan 2.0 ready If the recipe comes from ConanCenter check: https://conan.io/cci-v2.html If it is your recipe, check if it is updated to 2.0


ERROR: mngr/0.0.0-dev.0@autosar/bringup2: Error in build() method, line 30 cmake.test() ConanException: Cannot wrap command with different envs,['C:\Users\\.conan2\p\t\mngr6f49df387e9b7\b\build\Debug\generators\conanbuild.bat'] - ['C:\Users\\.conan2\p\t\mngr6f49df387e9b7\b\build\Debug\generators\conanrun.sh']

maitrey commented 1 year ago

FORDEBUGGING.zip Uploaded an example of how I am using it. But I tried meanwhile couple of other things , but nothing is working better than cmake.test() and add_test(). I would like to very much benefit from the advantages of conan-2.x but perhaps if this feature doesnot work , it might be preferred for cross compilation use-cases to stay with 1.56. Ideas that I tried, so far:

Any ideas or help is greatly appreciated.

memsharded commented 1 year ago

Hi @maitrey

I'd still like to understand how you are able to run executables for the host platform in the build platform when you are cross compiling. What system are you using? Maybe I am missing something, but lets say that you are building in a Windows machine "profile_build" with os=Windows, and you are cross building for a Linux embedded system "profile_host" with os=Linux. The tests belong to the "host" context, in this case, it would be the Linux system. If you try to actually execute those tests, as you are building in a Windows machine, those executables will not work.

What I am missing? do you have some kind of remote testing system? This is important to understand, because Conan is being confused, being generated files for both "build" and "run" environment, which are clearly not compatible, because they belong to different OSs.

maitrey commented 1 year ago

Could it be that , this was added in 2.x and now shows issues: environment.py


   if bool(bats + ps1s) + bool(shs) > 1:
        raise ConanException("Cannot wrap command with different envs,"
                             "{} - {}".format(bats+ps1s, shs))
``
maitrey commented 1 year ago

No I was wrong, this was existing in conan-1.56. Anyhow I understand the argument above from you and I am also clueless how did it work before. I see couple of differences in the settings.yml, in 1.56 I had:

# Only for cross building, 'os_build/arch_build' is the system that runs Conan
os_build: [Windows, WindowsStore, Linux, Macos, FreeBSD, SunOS, AIX, VxWorks]
arch_build: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, sh4le, e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7]

# Only for building cross compilation tools, 'os_target/arch_target' is the system for
# which the tools generate code
os_target: [Windows, Linux, Macos, Android, iOS, watchOS, tvOS, FreeBSD, SunOS, AIX, Arduino, Neutrino]
arch_target: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, asm.js, wasm, sh4le, e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7, xtensalx6, xtensalx106]

Does that make a difference?

maitrey commented 1 year ago

Now i think I know, in 2.x I use buildenv and in 1.56 I always used [env] because of which it generated only one .bat. Now conan2.x is explicit automatically has buildenv and runenv in profile and throws errors: In1.x: target_host=C:/toolbase/ndp/bin/ppc-vle standalone_toolchain=C:/toolbase/ndp/ cc_compiler=ppc-vle-gcc

[settings] os=RTOS arch=UC1 arch_build=x86_64 compiler=ppc-vle-gcc compiler.version=10.1 build_type=Release

[env] PATH=[$standalone_toolchain/bin, C:/MinGW/4.8.1/bin] CC=$target_host-gcc.exe LD=$target_host-gcc.exe AR=$target_host-ar.exe AS=$target_host-as RANLIB=$target_host-ranlib STRIP=$target_host-strip CFLAGS=-O2 -fno-tree-vrp -g -W CFLAGS_RELEASE=-O2 -g CFLAGS_DEBUG=-O2 LDFLAGS=-lgcc

[conf] tools.cmake.cmaketoolchain:generator=MinGW Makefiles

The tests are not using binaries that are generated for the target platform. Since I am not using the binaries for the target platform , is it then possible to use add_test triggered by cmake.test() by overriding this check? I have many simple tests like some document checks and static code analysis checks.

maitrey commented 1 year ago

@memsharded : Good Morning! Could I use: self.run("ctest") . There are some compliance reasons(internal) we have to run some checks like docu checks.So I have to run them after build process. Are there are any side effects of using it this way ?

maitrey commented 1 year ago

Another point to add:  I am cross compiling thats right but i donot use resulting binaries from the build for any tests .. For unit tests , I use tpt that internally uses mingw for compiling tests on windows.. But the check in environment.py , now means that anyone who is cross compiling cannot run any tests as it will generate a conanbuild.bat and a conanrun.sh and at this point there is an exception raised (Line 51).

 if bool(bats + ps1s) + bool(shs) > 1:
        raise ConanException("Cannot wrap command with different envs,"
                             "{} - {}".format(bats+ps1s, shs))
memsharded commented 1 year ago

The explanation of the issue is something like this:

This behavior seem correct, and aligned to the fact that some binaries intended for a cross-building scenario cannot be executed, and this is why I have been trying to understand the use case. Now I understand that your tests doesn't build for the same "host" configuration, which is unexpected, sounds a bit like hacky.

So you might need to customize the recipe somehow to implement this use case. Some things that you can try:

maitrey commented 1 year ago

Hi James, Sorry I saw your reply only today. I already understood why it did not work for me by looking into the source code of conan. I am using self.run(ctest) and this works for me, even without specifying any environment for me like I was asking 2 days ago. Many thanks for your reply and support. Ticket can be closed.