Skip to content
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

Add CONAN_CMAKE_TRY_COMPILE_TARGET_TYPE to env_vars #4706

Closed
peter-moran opened this issue Mar 9, 2019 · 10 comments
Closed

Add CONAN_CMAKE_TRY_COMPILE_TARGET_TYPE to env_vars #4706

peter-moran opened this issue Mar 9, 2019 · 10 comments

Comments

@peter-moran
Copy link

peter-moran commented Mar 9, 2019

In order to improve the capabilities of cross-building with Conan, I believe we should add an environmental variable CONAN_CMAKE_TRY_COMPILE_TARGET_TYPE that gets passed to CMake as CMAKE_TRY_COMPILE_TARGET_TYPE.

Why? -- CMake tests the compiler you give it, and CMAKE_TRY_COMPILE_TARGET_TYPE allows you to specify the target type it should build. In particular, you may need to set it to STATIC_LIBRARY for cross-compiling with toolchains that cannot link without custom flags or linker scripts.

A good example is the GNU Arm Embedded Toolchain, which requires set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) to work with Conan.

As it stands right now, Conan will pass CMake the Arm compiler I want to use (without having to modify the CMakeList.txt!) but CMake always fails to configure because the compiler cannot pass the test without this extra information. If we added this cmake variable to the cmake build tool, I would be able to use the Arm Embedded Toolchain on projects without having to update the CMakeList.txt, and it would likely benefit other compilers with similar limitations.

@Johnnyxy
Copy link

Hi there,
setting the CMake variable is possible without having to modify your CMakeLists.txt. You could try the following two options:

CMake definitions

Set the CMake variable directly using (if not already) the CMake build helper.

def build(self):
    cmake = CMake(self)
    cmake.definitions["CMAKE_TRY_COMPILE_TARGET_TYPE"] = "STATIC_LIBRARY"
    cmake.configure()
    cmake.build()
    ...    

Maybe you could analyze your given settings and detect if you have to set the CMake variable.
E.g.

def build(self):
    cmake = CMake(self)
    if (MY_TARGET_IS_EMBEDDED_ARM_CONDITION):
        cmake.definitions["CMAKE_TRY_COMPILE_TARGET_TYPE"] = "STATIC_LIBRARY"
    cmake.configure()
    cmake.build()
    ...    

Recipe options

You can create a recipe option that you can set on the command line for the install command or by a conan profile.

conan recipe:

class recipe(ConanFile):
    ...
    options = {"CMAKE_TRY_COMPILE_TARGET_TYPE": ["EXECUTABLE", "STATIC_LIBRARY", None])
    default_options = {"CMAKE_TRY_COMPILE_TARGET_TYPE": None)
    ...

    def build(self):
        cmake = CMake(self)
        if (self.options.CMAKE_TRY_COMPILE_TARGET_TYPE != None):
            cmake.definitions["CMAKE_TRY_COMPILE_TARGET_TYPE"] = self.options.CMAKE_TRY_COMPILE_TARGET_TYPE
        cmake.configure()
        cmake.build()
    ...    

Your conan profile for your ARM toolchain:

...
[options]
CMAKE_TRY_COMPILE_TARGET_TYPE="STATIC_LIBRARY"
...

conan command:

conan install ... --profile="PATH/TO/YOUR/PROFILENAME"

@peter-moran
Copy link
Author

Interesting, I didn't know you could pass arbitrary definitions, I'm sure that'll come in handy.

However, I'm realizing now that this is still not what I would need to make a fully fledged toolchain, because now I have to modify the conanfile to be ready to except my definition of CMAKE_TRY_COMPILE_TARGET_TYPE.

Every other part of my toolchain, such as the compiler binaries and build flags, can be specified in a Conan profile as an environmental variable. Conan even provides some environmental variables that are specific to cmake.

The ability to make a profile that could allow me to cross build any Conan project with my toolchain would be awesome, and CMAKE_TRY_COMPILE_TARGET_TYPE is the only thing holding that back.

@Johnnyxy
Copy link

Yes, you have to modify the Conan recipe. But you mentioned that you did not want to modify the CMakeLists.txt, so you have to do it in the conanfile for now.

You are right, there are some Conan environment variables that Conan uses to interact with CMake (like see 1, see 2 and see 3). Even as it would work with the recipe options way, a "transparent" integration of the CMake variable as you mentioned (CMAKE_TRY_COMPILE_TARGET_TYPE) would imply an addition of this one as Conan specific environment variable or some kind of detection logic in Conan or both.


What you could try is to abuse the CONAN_CMAKE_PROGRAM variable and pass the binary as well as your variable definition. I did not test this and it is certainly not recommended.

Windows environment variable set command:

set "CONAN_CMAKE_PROGRAM=cmake -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY"
conan install ...

@peter-moran
Copy link
Author

If there is support from the maintainers, I would gladly implement the addition of a Conan specific environment variable and modify the Conan's CMake build tool to pass that variable, essentially in the same way CONAN_CMAKE_TOOLCHAIN_FILE is.

@lasote lasote self-assigned this Mar 11, 2019
@lasote
Copy link
Contributor

lasote commented Mar 11, 2019

Hi, thanks to both for opening and commenting on this issue.
As it is a variable that "describes" somehow the compiler, it could make sense what you are requesting. So could declare that env var in your profile [env] section and Conan CMake build helper could adjust when present. I will discuss with the team about it.

@peter-moran
Copy link
Author

It is worth noting that CMAKE_TRY_COMPILE_TARGET_TYPE is only supported by CMake 3.6 and above. Before then, you have to use CMAKE_FORCE_C_COMPILER afaik.

@niosHD
Copy link
Contributor

niosHD commented Mar 20, 2019

Is there any reason why you can/want not set CMAKE_TRY_COMPILE_TARGET_TYPE as part of a cmake toolchain file?

As you mentioned, this variable is very toolchain specific and often needed when cross compiling for embedded architectures. Subsequently, having the setting in the toolchain file seems sensible and is, in my experience, also common in traditional (non conan) environments. While not feeling strongly, I am wondering if this additional feature is really useful considering that conan already has support for injecting cmake toolchain files into the build via the CONAN_CMAKE_TOOLCHAIN_FILE variable.

@peter-moran
Copy link
Author

Hmm, I don't think that is an unreasonable conclusion considering it is specific to cross compiling a cmake.

The reason I have not set CMAKE_TRY_COMPILE_TARGET_TYPE as part of a cmake toolchain file is that I am trying to support cross compiling by invoking cmake directly, rather than calling conan build.

However, I have made some progress since then. I found #2956, which is discussing the same goals as mine. That issue led me to https://github.com/pepe82sh/ConanCmakeToolchainGenerator which is a generator for toolchain files that would resolve the linked issue.

That is all to say, if ConanCmakeToolchainGenerator was adopted by conan and it included the feature pepe82sh/ConanCmakeToolchainGenerator#1 then I could add any extra initialization to the CONAN_CMAKE_TOOLCHAIN_FILE. But perhaps that is all a little too specific to my own project.

@kaidokert
Copy link
Contributor

kaidokert commented Jan 13, 2020

I've wrestled with the same thing. I would like this feature to be available as a user ( rather than upstream author editing CMakeLists or packager editing conanfile.py's )

If cmake_flags.py had an extension mechanism to pass in arbitrary CMake arguments at conan install .. invocation time, that would be awesome. Cross-compiling arbitrary packages would become much easier

For example, most header-only libraries would cross-compile with any baremetal toolchain without any issues.

Right now, i'm doing this in _cmake_cross_build_defines() which gets around the problem:

if os.getenv("CONAN_CMAKE_TRY_COMPILE_TARGET_TYPE", None):
  definitions["CMAKE_TRY_COMPILE_TARGET_TYPE"] = os.getenv("CONAN_CMAKE_TRY_COMPILE_TARGET_TYPE")

EDIT: Also noticed another request for generic Cmake flags passing in #1318, again in context of cross-compiling for CMAKE_NO_SYSTEM_FROM_IMPORTED

@memsharded
Copy link
Member

The build system integrations have completely changed since then, now based on toolchains CMakeToolchain, with specific features to inject toolchain files directly from profiles, like the [conf] tools.cmake.cmaketoolchain:user_toolchain.

So closing this as outdated, if there are further questions or issues, I'd suggest check the new integrations and open a new ticket. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants