conan-io / conan-center-index

Recipes for the ConanCenter repository
https://conan.io/center
MIT License
953 stars 1.74k forks source link

[package] emsdk/3.1.23: Cannot compile if emscripten headers are required. #14742

Closed Bam4d closed 1 year ago

Bam4d commented 1 year ago

Description

Hi,

We been using emscritpen and the emcmake and emmake wrappers provided by emsdk manually as defined in their documentation. This worked as expected and we easily compiled our .wasm libraries.

Recently we switched to using conan and now require a build using emsdk and cmake-conan. We've spent alot of time trying to get this to work and have come to an impasse where we need some help.

So far we have set up the dual profile as suggested in https://github.com/conan-io/conan/issues/10259 and we are using the suggested method of using conan install from the conan-make repo:

(taken from https://github.com/Bam4d/Griddly/blob/wasm_fixies/cmake/settings/Conan.cmake)

        conan_cmake_configure(
            REQUIRES 
                glm/0.9.9.8
                yaml-cpp/0.6.3
                spdlog/1.9.2
            OPTIONS
                gtest:build_gmock=True
            GENERATORS
                cmake
                cmake_find_package
                cmake_paths
        )

        conan_cmake_install(
            PATH_OR_REFERENCE .
            CONAN_COMMAND ${CONAN}
            ${CONAN_EXTRA_REQUIRES}
            OPTIONS
            ${CONAN_EXTRA_OPTIONS}
            PROFILE_HOST emsdk
            PROFILE_BUILD default
            BUILD missing
        )

        include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
        conan_basic_setup(TARGETS)

So when running this eveything installs OK and seems to build.... apart from the actual emscripten bindings/embind etc....

We get an error that the emscripten/bind.h headers cannot be found. It seems as though the emsdk package itself does not actually expose these to the build process at all.

Package and Environment Details

Conan profile

emsdk profile:

include(default)
[settings]
os=Emscripten
arch=wasm
compiler=clang
compiler.version=6.0
compiler.libcxx=libc++
[options]
[build_requires]
emsdk/3.1.23
[env]

I believe the "default" profile is autodetected with cmake.

Steps to reproduce

Firstly clone the Griddly repo and change to the wasm_fixies branch.

Then run the cmake steps in js/build.sh (If you run it directly it will complain about missing files but you can ignore this)

you can run the full build including some cleanup steps using:

cd js && ./configure.sh && ./build.sh

OR just run the cmake directly from the root directory.

cmake . -DWASM=ON && make

Logs

Everything works fine up untl this point:

-- Build files have been written to: /home/bam4d/qmul/Griddly/build_wasm
Consolidate compiler generated dependencies of target griddlyjs
[  1%] Building CXX object CMakeFiles/griddlyjs.dir/js/bindings/GriddlyJS.cpp.o
In file included from /home/bam4d/qmul/Griddly/js/bindings/GriddlyJS.cpp:1:
/home/bam4d/qmul/Griddly/js/bindings/GriddlyJS.hpp:1:10: fatal error: emscripten/bind.h: No such file or directory
    1 | #include <emscripten/bind.h>
      |          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/griddlyjs.dir/build.make:93: CMakeFiles/griddlyjs.dir/js/bindings/GriddlyJS.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:88: CMakeFiles/griddlyjs.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Nekto89 commented 1 year ago

I think that current conan approach would be to use CMakeToolchain generator before calling cmake. And pass generated cmake_toolchain.cmake through -DCMAKE_TOOLCHAIN_FILE option. https://docs.conan.io/en/latest/reference/conanfile/tools/cmake/cmaketoolchain.html

SpaceIm commented 1 year ago

I guess something like this should be added to package_info() of emsdk recipe, so that it can work properly in build systems not relying on CMake Toolchain file provided by emsdk:

        emsdk_sysroot = os.path.join(self._em_cache, "sysroot")
        self.conf_info.define("tools.build:sysroot", emsdk_sysroot)
        self.buildenv_info.define_path("SYSROOT", emsdk_sysroot)
        self.env_info.SYSROOT = emsdk_sysroot

(EDIT: no actually this suggestion breaks everything :p )

Bam4d commented 1 year ago

DCMAKE_TOOLCHAIN_FILE

Is this what the emcmake wrapper does? How do I use the CMakeToolchain generator in my case (i.e from within cmake if WASM is enabled?)

Bam4d commented 1 year ago

So im not getting anywhere useful with the toolchain generator... and its explicitly not recommended by the conan-cmake toolset: image

Bam4d commented 1 year ago

@Nekto89 @SpaceIm I have made a minimal reproducible example here:

https://github.com/Bam4d/conan-emscripten-test

Minimal reproducible example for fixing emsdk + conan + emscripten builds

Build the emscripten demo using cmake + conan

1. Builds a library using emscripten
2. Builds an executable (using emscripten) which Links to the libary -- THIS CURRENTLY FAILS

You can run the entire thing here:

./run-demo.sh
SpaceIm commented 1 year ago

@Bam4d I advice to submit your issue to cmake-conan unless it doesn't work also with recommended workflow (which is not cmake-conan, but CMakeToolchain).

Bam4d commented 1 year ago

unless it doesn't work also with recommended workflow which si CMakeToolchain

Can you help me understand what the "recommended workflow" is in this case? (I'm trying to avoid re-writing my entire build process again for emsdk to work)

@memsharded asked me to post this issue here, (Originally was in conan-cmake)

I'm not sure I understand conan enought to identify whether the error lies in the emsdk package or cmake-conan.

Thanks!

Bam4d commented 1 year ago

The equivalent ticket in conan-cmake https://github.com/conan-io/cmake-conan/issues/466

SpaceIm commented 1 year ago

I've tested on macOS with a CMakeToolchain workflow, and it works fine.

Minimal reproducible example with a CMakeLists.txt, conanfile.txt & main.cpp in root folder of the project:

CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(emsdk_test LANGUAGES CXX)

find_package(ZLIB REQUIRED)

add_executable(emsdk_test main.cpp)
target_link_libraries(emsdk_test PRIVATE ZLIB::ZLIB)

conanfile.txt

[requires]
zlib/1.2.13
[generators]
CMakeToolchain
CMakeDeps
VirtualBuildEnv

main.cpp

#include <zlib.h>

#include <emscripten/bind.h>

int main() {
    return 0;
}

default profile

[settings]
os=Macos
arch=x86_64
compiler=apple-clang
compiler.version=14
compiler.libcxx=libc++
build_type=Release

emscripten-wasm-clang profile

[settings]
os=Emscripten
arch=wasm
compiler=clang
compiler.version=15
compiler.libcxx=libc++
build_type=Release
[tool_requires]
emsdk/3.1.23

Commands:

conan install . -pr:b default -pr:h emscripten-wasm-clang -s build_type=Release -if cmake-build-release -b missing
source ./cmake-build-release/conanbuild.sh
cmake -S . -B cmake-build-release -DCMAKE_TOOLCHAIN_FILE=cmake-build-release/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build cmake-build-release --config Release

CMake configure log:

-- Using Conan toolchain: /Users/spaceim/test_emsdk/cmake-build-release/conan_toolchain.cmake
-- Conan: Target declared 'ZLIB::ZLIB'
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/spaceim/test_emsdk/cmake-build-release

CMake build log:

[ 50%] Building CXX object CMakeFiles/emsdk_test.dir/main.cpp.o
[100%] Linking CXX executable emsdk_test.js
[100%] Built target emsdk_test
Bam4d commented 1 year ago

Thanks loads! I will try this and keep my example repo so you can point people to it in the future :)

Bam4d commented 1 year ago

OK this all works now and I;ve updated the example to explain better how the emscripten example works :D

Thanks for all your help. I will close this issue now!

Bam4d commented 1 year ago

Hi again! Unforfunately I need to re-open this because the CMakeToolchain method seems to work OK for some third party libraries.... But for certain libraries it completely breaks the paths in the find_package() method.

So I added two test dependencies (glm and yaml-cpp) and I am printing the results of what find_package() does with and without the conan_toolchain.cmake

In both cases I am first running this:

conan install consumer/conanfile.txt --profile:host conan-profiles/emscripten.profile --profile:build default --build missing -if build_wasm

and then EITHER: cmake consumer -B build_wasm -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake OR cmake consumer -B build_wasm

The results of the find_package() are printed with:

find_package(ZLIB)
find_package(glm)
find_package(yaml-cpp)

message(STATUS Zlib: ${ZLIB_FOUND})
message(STATUS GLM: ${glm_FOUND})
message(STATUS yaml-cpp: ${yaml-cpp_FOUND})

message(STATUS Zlib: ${ZLIB_INCLUDE_DIRS})
message(STATUS GLM: ${glm_INCLUDE_DIRS})
message(STATUS yaml-cpp: ${yaml-cpp_INCLUDE_DIRS})

Result WITH toolchain

run.sh

-- Found ZLIB: 1.2.13 (found version "1.2.13") 
-- Library z found /home/bam4d/.conan/data/zlib/1.2.13/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/lib/libz.a
-- Found: /home/bam4d/.conan/data/zlib/1.2.13/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/lib/libz.a
-- Zlib:TRUE
-- GLM:1
-- yaml-cpp:1
-- Zlib:/home/bam4d/.conan/data/zlib/1.2.13/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/include
-- GLM:
-- yaml-cpp:

Finds zlib OK but fails to find the other packages and thus the build fails

Result WITHOUT toolchain

./run_notoolchain.sh

-- Found glm: 0.9.9.8 (found version "0.9.9.8") 
-- Conan: Using autogenerated Findyaml-cpp.cmake
-- Found yaml-cpp: 0.6.3 (found version "0.6.3") 
-- Library yaml-cpp found /home/bam4d/.conan/data/yaml-cpp/0.6.3/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/lib/libyaml-cpp.a
-- Found: /home/bam4d/.conan/data/yaml-cpp/0.6.3/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/lib/libyaml-cpp.a
-- Zlib:TRUE
-- GLM:TRUE
-- yaml-cpp:TRUE
-- Zlib:/home/bam4d/.conan/data/zlib/1.2.13/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/include
-- GLM:/home/bam4d/.conan/data/glm/0.9.9.8/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include
-- yaml-cpp:/home/bam4d/.conan/data/yaml-cpp/0.6.3/_/_/package/ed3213b5dc34976234aa8a4a92e51a91cf5f8751/include

The packages are found but then we are failing again with the error I originally opened this ticket for.

I've updated the demo repository with a branch with this code: https://github.com/Bam4d/conan-emscripten-test/tree/failing_dependencies

SpaceIm commented 1 year ago

You must not omit -DCMAKE_BUILD_TYPE during CMake configuration.

Bam4d commented 1 year ago

OK, added -DCMAKE_BUILD_TYPE=Debug and this does not change the outcome

SpaceIm commented 1 year ago

Works fine for me with commands I gave you above (conan install & cmake configuration must be called with the same build type obviously).

Bam4d commented 1 year ago

Thanks again for the pointers!

Rebuilt trying to use all the same setup that you did in your example... the only strange this is I have to add yaml-cpp differently than the other libraries or it does not build/link e.g:

target_link_libraries(main ZLIB::ZLIB glm::glm yaml-cpp)

(notice the lack of yaml-cpp::yaml-cpp) Not sure why this library is any different.

SpaceIm commented 1 year ago

(notice the lack of yaml-cpp::yaml-cpp) Not sure why this library is any different.

There is no rule, we follow upstream convention, and they can define any arbitrary name for their CMake imported target.