Open eigenwhat opened 2 years ago
find_package(SWIG)
only works when the PATH is configured correctly. When you would run the following commands, it will build correctly:
mkdir build && cd build
conan install ..
conan build ..
If you don't want conan to drive the compilation, you need modify your environment.
This can be done with the virtualrunenv
generator.
Modify you conanfile.py
slightly:
from conans import CMake, ConanFile, tools
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake_find_package", "virtualrunenv"
requires = "swig/4.0.2"
def build(self):
cmake = CMake(self)
cmake.verbose = True
cmake.configure()
cmake.build()
Then, you can do the following:
mkdir build && cd build
conan install ..
. activate_run.sh
cmake ..
Is this a peculiarity of SWIG's package or a limitation of Conan? It's very surprising to me to find that it can't prepare the search path for binaries the same way it can find libraries. In order to drive the build from Conan for our main project it would basically mandate switching to a conanfile.py
, which would be nontrivial. Using virtualrunenv
feels like more of a hack, but how well does it work when building with CLion?
Is this a peculiarity of SWIG's package or a limitation of Conan?
It's common behavior of operating systems: paths of binaries need to be added to the PATH
environment variable.
On my Linux system, conan created the swig package at /home/maarten/.conan/data/swig/4.0.2/_/_/package/ecb2d71ae4bad3b51dade00ec89140273402b5d7
.
So when I run the following, I can build your project without virtualenv
and without using conan as driver:
export PATH=/home/maarten/.conan/data/swig/4.0.2/_/_/package/ecb2d71ae4bad3b51dade00ec89140273402b5d7:$PATH
cmake ..
make
Using
virtualrunenv
feels like more of a hack, but how well does it work when building with CLion?
virtualenv
sets the environment variables for all dependencies.
Because you also need to set-up the paths, you need to somehow inform clion where all applications can be found.
I just tested with this conan plugin for CLion 2022.1, and can confirm I can build your project just fine.
...I know how the PATH
environment variable works, thank you very much.
That doesn't answer why CMake needs it to be in the environment's PATH
, and why the generated find configuration for SWIG can't tell CMake where to look, you know, the way it does so for libraries. Needing to set PATH
makes sense if you're relying on the stock find modules (i.e. what cmake_paths
was used for in the past), but this is a find module generated by Conan, so it knows exactly where everything should be. It could just set SWIG_EXECUTABLE
to the proper path with no searching required, just like it would when generating library targets. Having to tamper with the environment just to get this to work seems at odds with the entire premise of cmake_find_package
and descendant generators.
I just tested with this conan plugin for CLion 2022.1, and can confirm I can build your project just fine.
It can build with or without SWIG because the Conan-generated find module doesn't actually fail if the executable isn't found (because, and I repeat, it finds the library part just fine). If I add the following to the CMakeLists (above add_executable
):
if ("${SWIG_EXECUTABLE}" STREQUAL "" OR "${SWIG_EXECUTABLE}" STREQUAL "SWIG_EXECUTABLE-NOTFOUND")
message(FATAL_ERROR "Didn't work.")
else()
message("It looks like it worked? Check variables above and see if they make sense.")
endif()
It, in fact, doesn't work for me. (I will edit my initial sample project with this included.)
I'm beginning to think that any easy solution I can roll out to the rest of my team is hopeless because while I don't mind using the terminal to build things, it'll be one hard sell to make everyone else change their workflow just so we can use Conan to manage our build tools. Best I can hope for it seems is to convince them to budget time to rework our build system to be driven by Conan (i.e. move to a conanfile.py and port over our build configuration), and maybe have a dummy CMakeLists.txt
to bootstrap the process so it plays nicely with CLion. Or switch IDEs. Or give up.
...I know how the
PATH
environment variable works, thank you very much.
Yeah sorry, I just wanted to show that cmake needs extra information to find swig: conan does not store it in a location where cmake (or autotools) look for dependencies by default.
That doesn't answer why CMake needs it to be in the environment's
PATH
, and why the generated find configuration for SWIG can't tell CMake where to look, you know, the way it does so for libraries.
FindSWIG
uses find_program
to look for swig.
Here is a link to the source.
As you can read from the find_program
documentation, CMake looks in various locations.
Running the following commands all work (after running conan install ..
):
cmake .. -DCMAKE_PREFIX_PATH=/home/maarten/.conan/data/swig/4.0.2/_/_/package/ecb2d71ae4bad3b51dade00ec89140273402b5d7
export PATH=/home/maarten/.conan/data/swig/4.0.2/_/_/package/ecb2d71ae4bad3b51dade00ec89140273402b5d7/bin:$PATH
cmake ..
I hope that explains why CMake needs extra information where to find swig
.
Libraries need something similar.
When you'ld add a requirement to e.g. libjpeg
and do a find_package(JPEG REQUIRED)
, it won't find the conan libjpeg library automagically too.
Needing to set
PATH
makes sense if you're relying on the stock find modules (i.e. whatcmake_paths
was used for in the past), but this is a find module generated by Conan, so it knows exactly where everything should be. It could just setSWIG_EXECUTABLE
to the proper path with no searching required, just like it would when generating library targets. Having to tamper with the environment just to get this to work seems at odds with the entire premise ofcmake_find_package
and descendant generators.
Use the cmake
generator to configure cmake. Modify your CMakeLists.txt
script to:
cmake_minimum_required(VERSION 3.1)
project(Test)
option(USE_CONAN "Use Conan for dependency management" ON)
if(USE_CONAN)
include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
conan_basic_setup(TARGETS)
endif()
find_package(SWIG REQUIRED)
...
and conanfile.py
to:
from conans import ConanFile
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake_find_package", "cmake"
build_requires = "swig/4.0.2"
This allows an out-of-the box experience.
The USE_CONAN
cmake option still allows to use your system packages.
(conan 2.0 removed the cmake
generator
I'm beginning to think that any easy solution I can roll out to the rest of my team is hopeless because while I don't mind using the terminal to build things, it'll be one hard sell to make everyone else change their workflow just so we can use Conan to manage our build tools. Best I can hope for it seems is to convince them to budget time to rework our build system to be driven by Conan (i.e. move to a conanfile.py and port over our build configuration), and maybe have a dummy
CMakeLists.txt
to bootstrap the process so it plays nicely with CLion. Or switch IDEs. Or give up.
With the CMakeLists.txt
modification suggested above + the clion conan plugin, it should be able to build projects from within clion without touching the console.
FindSWIG uses find_program to look for swig.
Not when you use cmake_find_package
. Then it uses the generated find script, which in turn includes lib/cmake/conan-official-swig-targets.cmake
, which is part of the Conan package. It so happens to call find_program(SWIG_EXECUTABLE swig)
in the first line, but if it instead read find_program(SWIG_EXECUTABLE swig "${CMAKE_CURRENT_LIST_DIR}/../../bin")
it would find it perfectly without any fuss. If you could access some of the Conan-produced variables it could be made even more explicit.
If that's unworkable for whatever reason, I suppose I can produce the right search path myself by fishing out the package path from some other variables.
Use the
cmake
generator to configure cmake [...] This allows an out-of-the box experience.
What? No it doesn't. That doesn't work at all.
Use the
cmake
generator to configure cmake [...] This allows an out-of-the box experience.What? No it doesn't. That doesn't work at all.
You still need to use the Conan CLion plugin: https://blog.jetbrains.com/clion/2019/05/getting-started-with-the-conan-clion-plugin/
I know how to use the Conan CLion plugin. I've only been using it for the past few years. The question is and remains about having the executable search paths be set correctly without forcing anyone to do additional manual steps. I was hoping that I'd get advice in getting virtualrunenv
to work within CLion using the IDE's standard build commands, or some other solution that prepares the environment. The cmake
generator does not help.
At this point I think I will just modify the SWIG package and fix the problem myself as I described earlier, because I'm tired of talking in circles.
I have recently run into the same issue.
I have a very similar setup as @eigenwhat described and I am wondering why PATHS ${CONAN_BIN_DIRS_SWIG} NO_DEFAULT_PATH
was removed from find_program(SWIG_EXECUTABLE swig)
in this commit.
If I add that back to the conan-official-swig-targets.cmake
file (and if I use cmake
generator and include conanbuildinfo.cmake
in my CMakeLists.txt) then it seems to work for me.
I'm curious and maybe @madebr can shed some light on why that change was made to conan-official-swig-targets.cmake
?
@steffenhk does it need to be re-opened?
It’s an open problem that hasn’t been resolved. I closed the issue originally because I ran out of patience trying to get a straight answer, not because anything got fixed.
So we have investigated this for more than a day.
Why does the swig/4.0.2 contain the conan-official-swig-targets.cmake in the first place ? if the package location root was added to the CMAKE_PREFIX_PATH, instead of the package/lib/cmake path, then it will work out of the box, since find_program will look in CMAKE_PREFIX_PATH before it looks in the PATH environment variable.
This was added in https://github.com/conan-io/conan-center-index/pull/4534
Note how that pr also adds cmake_find_package
to the generators of the test package.
I think this was done because on Windows, cmake is not case sensitive and will match the conan generated Findswig.cmake
.
An alternative could be to let conan generate FindSWIGDoNotUsecmake
instead of FindSWIG.cmake
.
Would another alternative be to also append "" to the list of cpp_info.builddirs in the swig conanfile in order to add the swig package root to CMAKE_PREFIX_PATH
?
Then using find_package(SWIG)
when using either cmake_paths
or cmake_find_package
generators should both work, since both the CMake provided and the conan generated FindSWIG.cmake
will find the swig executable using find_program
.
Any update on this regard? Comment by @soerengustenhoff seems to point in the right direction.
I think I'm suffering from the same problem here, using Conan v2 with the cmake-conan integration that relies on find_package and CMakeDeps. However, Conan's SWIGConfig.cmake "shadows" the official CMake find script which is required to pull in the CMake functions etc to create SWIG targets.
Perhaps one solution would be for Conan to not intercept find_package with the COMPONENTS parameter, but am I missing something here on how Conan and SWIG should be integrating when using Conan's find_package integration?
I agree with @madebr that Conan's SWIGConfig.cmake should get a different name so that we can use CMake's FindSwig script as usual. And if we're not supposed to use that, I couldn't find any documentation on what we should be using instead?
Update: having slept on it, I found the solution this morning, this syntax works to run the official CMake FindSWIG.cmake script and get the SWIG_USE_FILE variable set:
find_package(SWIG
COMPONENTS csharp
REQUIRED
MODULE
BYPASS_PROVIDER
)
Package and Environment Details (include every applicable attribute)
Conan profile (output of
conan profile show default
orconan profile show <profile>
if custom profile is in use)Steps to reproduce (Include if Applicable)
conanfile.py
``` from conans import CMake, ConanFile, tools class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" generators = "cmake_find_package" requires = "swig/4.0.2" def build(self): cmake = CMake(self) cmake.verbose = True cmake.configure() cmake.build() ```CMakeLists.txt
``` cmake_minimum_required(VERSION 3.1) project(Test) set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR} ${CMAKE_PREFIX_PATH}) find_package(SWIG REQUIRED) include(UseSWIG) message("SWIG_DIR: ${SWIG_DIR}") message("SWIG_EXECUTABLE: ${SWIG_EXECUTABLE}") if ("${SWIG_EXECUTABLE}" STREQUAL "" OR "${SWIG_EXECUTABLE}" STREQUAL "SWIG_EXECUTABLE-NOTFOUND") message(FATAL_ERROR "Didn't work.") else() message("It looks like it worked? Check variables above and see if they make sense.") endif() add_executable(test main.cpp) ```main.cpp
``` int main() { return 0; } ```If I build this the usual way, it's unable to find the SWIG executable. However, if I build it as if it were a test package, it correctly populates
SWIG_DIR
,SWIG_EXECUTABLE
, etc. I've tried this with and without thecmake
generator, tried it withcmake_find_package_multi
,CMakeDeps
, etc, and nothing works.Logs (Include/Attach if Applicable)
conan test . swig/4.0.2@
``` SWIG_DIR: /Users/developer/.conan/data/swig/4.0.2/_/_/package/099d7b9cd06e9bd11e92b9a2ddf3b29cd986fdcb/bin/swig/swiglib SWIG_EXECUTABLE: /Users/developer/.conan/data/swig/4.0.2/_/_/package/099d7b9cd06e9bd11e92b9a2ddf3b29cd986fdcb/bin/swig ```mkdir build && cd build && conan install .. && cmake ..
``` SWIG_DIR: SWIG_EXECUTABLE: SWIG_EXECUTABLE-NOTFOUND ```