Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
695ba52
emsdk: added new recipe
perseoGI Jun 13, 2025
ac1c0d2
Merge branch 'main' into pgi/new/emsdk
czoido Jun 16, 2025
8f27571
wip
czoido Jun 16, 2025
12820bd
wip
czoido Jun 16, 2025
1768ae6
wip
czoido Jun 16, 2025
8bfa242
wip
czoido Jun 16, 2025
240b479
wip
czoido Jun 16, 2025
e01773a
wip
czoido Jun 16, 2025
4c44611
wip
perseoGI Jun 16, 2025
e62adda
Removed requirements
perseoGI Jun 17, 2025
334f376
try to fix output
czoido Jun 17, 2025
48823f6
Updated profiles, readme and ci
perseoGI Jun 17, 2025
06b9bd6
Updated CI, build only changed recipes
perseoGI Jun 17, 2025
43ab52f
Updated readme
perseoGI Jun 17, 2025
ecb363a
Moved general config to base CI profile
perseoGI Jun 19, 2025
fa69614
Fix error
perseoGI Jun 19, 2025
d08d241
Fix error
perseoGI Jun 19, 2025
44f11d9
Added user_toolchain example on native profile
perseoGI Jun 24, 2025
c080b28
Restore build_folder_vars
perseoGI Jun 25, 2025
81f7789
Added threads comment
perseoGI Jun 25, 2025
6ff3792
Removed unneded min node version
perseoGI Jun 25, 2025
c5746ce
Update requirements.txt
czoido Jul 1, 2025
3c475c9
Removed asmjs profile
perseoGI Jul 1, 2025
9736f29
Applied some review suggestions
perseoGI Jul 2, 2025
9ec67da
Removed unneded builddirs environment as already included by Emscript…
perseoGI Jul 3, 2025
073931e
Removed auto install conf in profile
perseoGI Jul 3, 2025
64ef64c
Restored original test_package and created test_example
perseoGI Jul 4, 2025
b1fe0cb
Fix ci
perseoGI Jul 4, 2025
6e335fb
Testing publish profiles workflow
perseoGI Jul 4, 2025
cbc1e53
WIP
perseoGI Jul 4, 2025
a5ed161
WIP
perseoGI Jul 4, 2025
c6aae81
Publish profiles
perseoGI Jul 4, 2025
dfe8b47
Publish profiles
perseoGI Jul 4, 2025
8dc22f5
Publish profiles
perseoGI Jul 4, 2025
92be15d
Publish profiles
perseoGI Jul 4, 2025
516d065
Removed support for multi versions in CI
perseoGI Jul 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions recipes/emsdk/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sources:
"4.0.10":
url: "https://github.com/emscripten-core/emsdk/archive/4.0.10.tar.gz"
sha256: "2497b55ddbba9bf9be2d18cfca3e973d40a0cfaa8d18f6caacb882a65b2faf1c"
145 changes: 145 additions & 0 deletions recipes/emsdk/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import os
from pathlib import Path

from conan import ConanFile
from conan.tools.build import cross_building
from conan.tools.env import Environment, VirtualBuildEnv
from conan.tools.files import chdir, copy, get
from conan.tools.layout import basic_layout

required_conan_version = ">=2.1"


class EmSDKConan(ConanFile):
name = "emsdk"
description = "Emscripten SDK. Emscripten is an Open Source LLVM to JavaScript compiler"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/kripken/emscripten"
topics = ("emsdk", "emscripten", "sdk", "emcc", "em++", "nodejs")
license = "MIT"
package_type = "application"
settings = "os", "arch"
upload_policy = "skip"
build_policy = "missing"

def layout(self):
basic_layout(self, src_folder="src")

def source(self):
get(self, **self.conan_data["sources"][self.version], destination=self.source_folder, strip_root=True)

@property
def _relative_paths(self):
return ["bin", os.path.join("bin", "upstream", "emscripten")]

@property
def _paths(self):
return [os.path.join(self.package_folder, path) for path in self._relative_paths]

@property
def _emsdk(self):
return os.path.join(self.package_folder, "bin")

@property
def _emscripten(self):
return os.path.join(self.package_folder, "bin", "upstream", "emscripten")

@property
def _em_config(self):
return os.path.join(self.package_folder, "bin", ".emscripten")

@property
def _em_cache(self):
return os.path.join(self.package_folder, "bin", ".emscripten_cache")

@property
def _node_path(self):
subfolders = [path for path in (Path(self.package_folder) / "bin" / "node").iterdir() if path.is_dir()]
if len(subfolders) != 1:
return None
return os.path.join("bin", "node", subfolders[0].name, "bin")

def generate(self):
env = Environment()
env.prepend_path("PATH", self._paths)
env.define_path("EMSDK", self._emsdk)
env.define_path("EMSCRIPTEN", self._emscripten)
env.define_path("EM_CONFIG", self._em_config)
env.define_path("EM_CACHE", self._em_cache)
env.vars(self, scope="emsdk").save_script("emsdk_env_file")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not very clear who is using this file in this scope.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also confusing that the PATHs of this file are pointing to the package_folder/something paths, that doesn't really exist when the build() method runs, and it might even not be defined with package_folder=None for local conan build or conan install operations.


# To avoid issues when cross-compiling or with not common arch in profiles we need to set EMSDK_ARCH
# This is important for the emsdk install command
env = VirtualBuildEnv(self)
# Special consideration for armv8 as emsdk expects "arm64"
arch = "arm64" if str(self.settings.arch) == "armv8" else str(self.settings.arch)
env.environment().define("EMSDK_ARCH", arch)
env.generate()

def build(self):
with chdir(self, self.source_folder):
emsdk = "emsdk.bat" if self.settings_build.os == "Windows" else "./emsdk"
self.run(f"{emsdk} install latest")
self.run(f"{emsdk} activate latest")

def package(self):
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
copy(self, "*", src=self.source_folder, dst=os.path.join(self.package_folder, "bin"))
if not cross_building(self):
self.run("embuilder build MINIMAL", env=["conanemsdk", "conanrun"]) # force cache population
# Avoid cache failures in case this package is uploaded as paths in sanity.txt are absolute
os.remove(os.path.join(self._em_cache, "sanity.txt"))

def _define_tool_var(self, value):
suffix = ".bat" if self.settings.os == "Windows" else ""
path = os.path.join(self._emscripten, f"{value}{suffix}")
return path

def package_info(self):
self.cpp_info.bindirs = self._relative_paths + [self._node_path]
self.cpp_info.includedirs = []
self.cpp_info.libdirs = []
self.cpp_info.resdirs = []

# If we are not building for Emscripten, probably we don't want to inject following environment variables,
# but it might be legit use cases... until we find them, let's be conservative.
if not hasattr(self, "settings_target") or self.settings_target is None:
return

if self.settings_target.os != "Emscripten":
self.output.warning(
f"You've added {self.name}/{self.version} as a build requirement, while os={self.settings_target.os} != Emscripten"
)
return

toolchain = os.path.join(
self.package_folder, "bin", "upstream", "emscripten", "cmake", "Modules", "Platform", "Emscripten.cmake"
)
self.conf_info.prepend("tools.cmake.cmaketoolchain:user_toolchain", toolchain)

self.buildenv_info.define_path("EMSDK", self._emsdk)
self.buildenv_info.define_path("EMSCRIPTEN", self._emscripten)
self.buildenv_info.define_path("EM_CONFIG", self._em_config)
self.buildenv_info.define_path("EM_CACHE", self._em_cache)

compiler_executables = {
"c": self._define_tool_var("emcc"),
"cpp": self._define_tool_var("em++"),
}
self.conf_info.update("tools.build:compiler_executables", compiler_executables)
self.buildenv_info.define_path("CC", compiler_executables["c"])
self.buildenv_info.define_path("CXX", compiler_executables["cpp"])
self.buildenv_info.define_path("AR", self._define_tool_var("emar"))
self.buildenv_info.define_path("NM", self._define_tool_var("emnm"))
self.buildenv_info.define_path("RANLIB", self._define_tool_var("emranlib"))
self.buildenv_info.define_path("STRIP", self._define_tool_var("emstrip"))

self.cpp_info.builddirs = [
os.path.join("bin", "releases", "src"),
os.path.join("bin", "upstream", "emscripten", "cmake", "Modules"),
os.path.join("bin", "upstream", "emscripten", "cmake", "Modules", "Platform"),
os.path.join("bin", "upstream", "emscripten", "system", "lib", "libunwind", "cmake", "Modules"),
os.path.join("bin", "upstream", "emscripten", "system", "lib", "libunwind", "cmake"),
os.path.join("bin", "upstream", "emscripten", "tests", "cmake", "target_library"),
os.path.join("bin", "upstream", "lib", "cmake", "llvm"),
]
16 changes: 16 additions & 0 deletions recipes/emsdk/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from conan import ConanFile
from conan.tools.build import can_run


class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"

def requirements(self):
self.requires(self.tested_reference_str)

def test(self):
# Check the package provides working binaries
if can_run(self):
self.run("emcc -v", env="conanrun")
self.run("em++ -v", env="conanrun")
self.run("node -v", env="conanrun")
15 changes: 15 additions & 0 deletions recipes/emsdk/all/test_package/profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[settings]
build_type=Release
compiler=emcc
compiler.cppstd=17
compiler.libcxx=libc++
compiler.version=4.0.10
os=Emscripten

[tool_requires]
emsdk/4.0.10
ninja/[*]

[conf]
# Set Ninja as default generator as it is faster and will sove issues on Windows
tools.cmake.cmaketoolchain:generator=Ninja
3 changes: 3 additions & 0 deletions recipes/emsdk/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
versions:
"4.0.10":
folder: all