conan-io / conan

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

How do I specify a custom toolchain.txt file to cmake #160

Closed nlbutts closed 7 years ago

nlbutts commented 8 years ago

Is there a way to specify a custom toolchain.txt file to cmake for cross compiling?

memsharded commented 8 years ago

I think it should be possible, for example, I'd try to do from my conanfile.py something like:

def build(self):
    if self.settings.arch == "armv6" and platform.system() == "Windows":
        toolchain = "-DUSE_TOOLCHAIN=mytoolchain.txt"
    else:
        toolchain = ""
    self.run("cmake ..... %s" % toolchain)

Then, in my CMakeLists.txt:

if(USE_TOOLCHAIN)
     # Do whatever is needed to load or use mytoolchain.txt
endif()

Is this what you are looking for? Please tell me, thanks!

astralien3000 commented 8 years ago

The problem is, if the required packages also need to be compiled with this toolchain (for example, a cross-compiler, or an option that need the library to be compiled with this option), what happens ?

memsharded commented 8 years ago

If you are talking about packages that use CMake exclusively, possibly, something can be done. The problem is that some packages, they don't use CMake at all, but Makefiles or other tools.

I will have a look for CMake, check if something can be done. Are you interested in cross-building to any specific platform or just in general?

astralien3000 commented 8 years ago

I use CMake for my personal work, but I likely need to use libraries that use Makefiles (or Scons, etc...).

I am interested in cross-compiling to microcontrollers (AVR, ARM, mainly). The problem is that, in this field, for each library, there is a custom build chain. That is also why I am interested in Conan for a few weeks. The problem is that I haven't found a clean way to "propagate" the target microcontroller over the conan packages.

memsharded commented 8 years ago

Unfortunately, there is no generic way to do a cross-building, as we do-not enforce the use of a specific build system, and thus there is nothing conan can do to indicate the packages that they should cross-build to a specific target processor.

Speaking generally, there could be two approaches for a package manager:

  1. The imperative one: Enforce the build system to realize a generic interface. With this approach, package creators would have to adapt their packages build system to the specific package manager interface. Forcing CMake would be the case, so any cmake toolchain could be used for all packages. This approach has the (huge) inconvenient that existing libraries with other build systems (e.g. Boost, OpenSSL...) would need to implement their custom build under CMake. Developing such a CMake project for projects like Boost is a huge task, so package creators would never contribute such packages.
  2. The lazy one: Use an abstract "soft" layer over any build system. Is the conan approach. Using settings or options you can already indicate a package that you want to cross-build to a certain target, but the underlaying build system simply could not be prepared. So there is no generic way to tell any package to be cross-built to any target system, and cross-build support is added to the packages on demand/collaboratively when the users requests and need it.

We'd love to implement a generic way of providing cross-building for all packages, but in our opinion the burdens for package creators outweight the advantages, so that is why we decided for the 2nd approach.

Hopefully, in many cases, adding the cross-platform support for the packages you need, could be done by improving over the existing packages, whatever build-system they use. Each package could have a custom build chain, each one different. Probably the use of "package generators" could be useful in this case if some of them need to share the toolchain, so we can manage toolchains as packages, with their versions, upload and collaborate over them.

I would suggest to try to move forward, and solve package problems as they come. Do you need Boost for your project? Probably not for AVR. Maybe for a powerful ARM? Lets check if the package can be improved, probably Boost build system is well prepared for cross-building, and just tuning a couple of lines in the package recipe is enough for your use case. As soon as some repetitive task is detected (e.g. many packages using CMake where we can plug-in a toolchain), lets raise an issue and transform it to a conan feature to help in that concrete task.

astralien3000 commented 8 years ago

I agree with you for the 2nd choice. I don't really need Conan to manage the toolchain, and I don't ask for this feature. I just would like to find the better way to give to each package the information of compiling itself for some target. The packages could after that use the toolchain they want (which could be in an other dedicated package, as you mentioned).

One way of doing it is to use the settings.yml configuration file. I could add a field like :

target: [avr, cortex-m0+, cortex-m3, cortex-m4, ...]

But one problem is that I have to enumerate all the target my packages can handle (which is a LOT of things). And the other problem is that if a package manages a new target, it can't modify the settings.yml in a clean way (since it is a user configuration file).

I have seen that there is an "option" system, which can be "declared" by the package. But It seems like you need to specify the option for each used package.

Maybe I am not right, I am quite new to Conan.

memsharded commented 8 years ago

You got it quite right actually.

The settings.yml has been created to define some "standard" names over the settings. As each different configuration of settings and options creates a different hash (SHA1) which is the ID of the respective binary, it is necessary some consensus about the settings names and values. So we all use "Visual Studio" instead of "MSVC", "Visual", "VStudio"...

You are also right that the target for embedded is clearly a setting, and as such it should be added to settings.yml. In fact I think that this discussion could be of interest to @weatherhead99 and @nlbutts as related to issue #86.

I am really looking forward to merging in the conan default settings.yml these settings, and define some common consensus about this. I think having even hundreds of values for the target setting shouldn't be a big problem either. So, if someone creates a package that supports a new target, and such target is not listed in the conan default settings.yml, the best would be to contribute it with a PR. In the meantime, they could add it locally in their settings.yml, and their package consumers will be notified. Using a not listed value in settings.yml, results in an error, so the consumer can notice and add such a value locally in their settings.yml. This can be a small issue, but will only happen in the transitions, and until the target setting is estabilized.

If you are thinking about an "ANY" option for a setting, so defining target=ANY in settings.yml could be possible. Then the problem is translated to package creators, and one package creators could use if self.settings.target == "CortexM3" and another package creators would decide to use if self.settings.target == "cortex-m3, so both packages will not be usable in the same project.

astralien3000 commented 8 years ago

You are right, it is better to have the same name for every package. So, enabling the package to change the settings.yml is not a good idea. Neither is enabling the packages to define their own settings.

I think it is better to continue on the issue #86, since it is more into the topic.

memsharded commented 7 years ago

This is related to the cross-building issue: https://github.com/conan-io/conan/issues/675#issuecomment-310920973

As explained in that comment, now it is much easier to provide and inject toolchains, using environment variables, build_requires, and convenient using profiles.

As I think there is not action required from us, this issue can be closed, but please re-open or comment if necessary. Thanks!