Skip to content

Commit

Permalink
(#15317) Add bimg
Browse files Browse the repository at this point in the history
* Add bimg with locally tested scripts

* Access conandata of bx directly for getting its source

* Fix pattern mistake that would omit prefixed libs (like those on not-windows)

* Remove fPIC option
Remove unnecessary @ in requires
Further clarify why we need bx source

* Make test_v1_package use test_package's source

---------

Co-authored-by: Raziel Alphadios <raziely@gmail.com>
  • Loading branch information
RazielXYZ and RazielZ authored Feb 13, 2023
1 parent 479d2eb commit 1f36ae8
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 0 deletions.
4 changes: 4 additions & 0 deletions recipes/bimg/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sources:
"cci.20230114":
url: "https://github.com/bkaradzic/bimg/archive/7afa2419254fd466c013a51bdeb0bee3022619c4.tar.gz"
sha256: "664D2DB41B60E1BEA473898427CD71D43CD33397A24596F1A2CF269D324A305D"
246 changes: 246 additions & 0 deletions recipes/bimg/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
from conan import ConanFile
from conan.tools.files import copy, get, rename
from conan.tools.build import check_min_cppstd
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, check_min_vs, is_msvc_static_runtime
from conan.tools.scm import Version
from conan.errors import ConanInvalidConfiguration
from conan.tools.microsoft import MSBuild, VCVars
from conan.tools.gnu import Autotools, AutotoolsToolchain
from conan.tools.env import VirtualBuildEnv
from pathlib import Path
import os

required_conan_version = ">=1.50.0"


class bimgConan(ConanFile):
name = "bimg"
license = "BSD-2-Clause"
homepage = "https://github.com/bkaradzic/bimg"
url = "https://github.com/conan-io/conan-center-index"
description = "Image library providing loading, saving, conversions and other utilities."
topics = ("image", "graphics")
settings = "os", "compiler", "arch", "build_type"
options = {"tools": [True, False]}
default_options = {"tools": False}

@property
def _bx_folder(self):
return "bx"

@property
def _bimg_folder(self):
return "bimg"

@property
def _bimg_path(self):
return os.path.join(self.source_folder, self._bimg_folder)

@property
def _genie_extra(self):
genie_extra = ""
if is_msvc(self) and not is_msvc_static_runtime(self):
genie_extra += " --with-dynamic-runtime"
if self.options.tools:
genie_extra += " --with-tools"
return genie_extra

@property
def _lib_target_prefix(self):
if self.settings.os == "Windows":
return "libs\\"
else:
return ""

@property
def _tool_target_prefix(self):
if self.settings.os == "Windows":
return "tools\\"
else:
return ""

@property
def _projs(self):
projs = [f"{self._lib_target_prefix}bimg", f"{self._lib_target_prefix}bimg_decode", f"{self._lib_target_prefix}bimg_encode"]
if self.options.tools:
projs.extend([f"{self._lib_target_prefix}texturec"])
return projs

@property
def _compiler_required(self):
return {
"gcc": "8",
"clang": "3.3",
"apple-clang": "5",
}

@property
def _bx_version(self): #mapping of bimg version to required/used bx version
return {"cci.20230114": "cci.20221116"}

@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)

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

def requirements(self):
self.requires(f"bx/{self._bx_version[self.version]}")

def validate(self):
if self.settings.compiler.get_safe("cppstd"):
check_min_cppstd(self, 14)
check_min_vs(self, 191)
if not is_msvc(self):
try:
minimum_required_compiler_version = self._compiler_required[str(self.settings.compiler)]
if Version(self.settings.compiler.version) < minimum_required_compiler_version:
raise ConanInvalidConfiguration("This package requires C++14 support. The current compiler does not support it.")
except KeyError:
self.output.warn("This recipe has no checking for the current compiler. Please consider adding it.")

def build_requirements(self):
self.tool_requires("genie/1170")
if not is_msvc(self) and self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")

def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True,
destination=os.path.join(self.source_folder, self._bimg_folder))
# bimg's genie project, and the projects generated by it, expect bx source to be present on the same relative root as bimg's in order to build
# usins a pre-built bx instead would require significant changes to the genie project but may be worth looking into in the future
get(self, **self.dependencies["bx"].conan_data["sources"][self._bx_version[self.version]], strip_root=True,
destination=os.path.join(self.source_folder, self._bx_folder))

def generate(self):
vbe = VirtualBuildEnv(self)
vbe.generate()
if is_msvc(self):
tc = VCVars(self)
tc.generate()
else:
tc = AutotoolsToolchain(self)
tc.generate()

def build(self):
if is_msvc(self):
# Conan to Genie translation maps
vs_ver_to_genie = {"17": "2022", "16": "2019", "15": "2017",
"193": "2022", "192": "2019", "191": "2017"}

# Use genie directly, then msbuild on specific projects based on requirements
genie_VS = f"vs{vs_ver_to_genie[str(self.settings.compiler.version)]}"
genie_gen = f"{self._genie_extra} {genie_VS}"
self.run(f"genie {genie_gen}", cwd=self._bimg_path)

msbuild = MSBuild(self)
# customize to Release when RelWithDebInfo
msbuild.build_type = "Debug" if self.settings.build_type == "Debug" else "Release"
# use Win32 instead of the default value when building x86
msbuild.platform = "Win32" if self.settings.arch == "x86" else msbuild.platform
msbuild.build(os.path.join(self._bimg_path, ".build", "projects", genie_VS, "bimg.sln"), targets=self._projs)
else:
# Not sure if XCode can be spefically handled by conan for building through, so assume everything not VS is make
# gcc-multilib and g++-multilib required for 32bit cross-compilation, should see if we can check and install through conan

# Conan to Genie translation maps
compiler_str = str(self.settings.compiler)
compiler_and_os_to_genie = {"Windows": f"--gcc=mingw-{compiler_str}", "Linux": f"--gcc=linux-{compiler_str}",
"FreeBSD": "--gcc=freebsd", "Macos": "--gcc=osx",
"Android": "--gcc=android", "iOS": "--gcc=ios"}
gmake_os_to_proj = {"Windows": "mingw", "Linux": "linux", "FreeBSD": "freebsd", "Macos": "osx", "Android": "android", "iOS": "ios"}
gmake_arch_to_genie_suffix = {"x86": "-x86", "x86_64": "-x64", "armv8": "-arm64", "armv7": "-arm"}
os_to_use_arch_config_suffix = {"Windows": False, "Linux": False, "FreeBSD": False, "Macos": True, "Android": True, "iOS": True}

build_type_to_make_config = {"Debug": "config=debug", "Release": "config=release"}
arch_to_make_config_suffix = {"x86": "32", "x86_64": "64"}
os_to_use_make_config_suffix = {"Windows": True, "Linux": True, "FreeBSD": True, "Macos": False, "Android": False, "iOS": False}

# Generate projects through genie
genieGen = f"{self._genie_extra} {compiler_and_os_to_genie[str(self.settings.os)]}"
if os_to_use_arch_config_suffix[str(self.settings.os)]:
genieGen += f"{gmake_arch_to_genie_suffix[str(self.settings.arch)]}"
genieGen += " gmake"
self.run(f"genie {genieGen}", cwd=self._bimg_path)

# Build project folder and path from given settings
projFolder = f"gmake-{gmake_os_to_proj[str(self.settings.os)]}"
if self.settings.os == "Windows" or compiler_str not in ["gcc", "apple-clang"]:
projFolder += f"-{compiler_str}" #mingw-gcc or mingw-clang for windows; -clang for linux (where gcc on linux has no extra)
if os_to_use_arch_config_suffix[str(self.settings.os)]:
projFolder += gmake_arch_to_genie_suffix[str(self.settings.arch)]
proj_path = os.path.sep.join([self._bimg_path, ".build", "projects", projFolder])

# Build make args from settings
conf = build_type_to_make_config[str(self.settings.build_type)]
if os_to_use_make_config_suffix[str(self.settings.os)]:
conf += arch_to_make_config_suffix[str(self.settings.arch)]
if self.settings.os == "Windows":
mingw = "MINGW=$MINGW_PREFIX"
proj_path = proj_path.replace("\\", "/") # Fix path for msys...
else:
mingw = ""
autotools = Autotools(self)
# Build with make
for proj in self._projs:
autotools.make(target=proj, args=["-R", f"-C {proj_path}", mingw, conf])

def package(self):
# Set platform suffixes and prefixes
if self.settings.os == "Windows":
lib_pat = "*bimg*.lib"
package_lib_prefix = ""
elif self.settings.os in ["Linux", "FreeBSD"]:
lib_pat = "*bimg*.a"
package_lib_prefix = "lib"
elif self.settings.os == "Macos":
lib_pat = "*bimg*.a"
package_lib_prefix = "lib"

# Get build bin folder
for bimg_out_dir in os.listdir(os.path.join(self._bimg_path, ".build")):
if not bimg_out_dir=="projects":
build_bin = os.path.join(self._bimg_path, ".build", bimg_out_dir, "bin")
break

# Copy license
copy(self, pattern="LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self._bimg_path)
# Copy includes
copy(self, pattern="*.h", dst=os.path.join(self.package_folder, "include"), src=os.path.join(self._bimg_path, "include"))
# Copy libs
copy(self, pattern=lib_pat, dst=os.path.join(self.package_folder, "lib"), src=build_bin, keep_path=False)
# Copy tools
if self.options.tools:
copy(self, pattern="texturec*", dst=os.path.join(self.package_folder, "bin"), src=build_bin, keep_path=False)

# Rename for consistency across platforms and configs
for bimg_file in Path(os.path.join(self.package_folder, "lib")).glob("*bimg*"):
fExtra = ""
if bimg_file.name.find("encode") >= 0:
fExtra = "_encode"
elif bimg_file.name.find("decode") >= 0:
fExtra = "_decode"
rename(self, os.path.join(self.package_folder, "lib", bimg_file.name),
os.path.join(self.package_folder, "lib", f"{package_lib_prefix}bimg{fExtra}{bimg_file.suffix}"))
if self.options.tools:
for bimg_file in Path(os.path.join(self.package_folder, "bin")).glob("*texturec*"):
rename(self, os.path.join(self.package_folder, "bin", bimg_file.name),
os.path.join(self.package_folder, "bin", f"texturec{bimg_file.suffix}"))

def package_info(self):
self.cpp_info.includedirs = ["include"]
self.cpp_info.libs = ["bimg_encode", "bimg_decode", "bimg"]

self.cpp_info.set_property("cmake_file_name", "bimg")
self.cpp_info.set_property("cmake_target_name", "bimg::bimg")
self.cpp_info.set_property("pkg_config_name", "bimg")

# TODO: to remove in conan v2 once cmake_find_package_* generators removed
self.cpp_info.filenames["cmake_find_package"] = "bimg"
self.cpp_info.filenames["cmake_find_package_multi"] = "bimg"
self.cpp_info.names["cmake_find_package"] = "bimg"
self.cpp_info.names["cmake_find_package_multi"] = "bimg"
9 changes: 9 additions & 0 deletions recipes/bimg/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.8)

project(test_package LANGUAGES CXX)

find_package(bimg REQUIRED CONFIG)

add_executable(${PROJECT_NAME} test_package.cpp)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
target_link_libraries(${PROJECT_NAME} bimg::bimg)
29 changes: 29 additions & 0 deletions recipes/bimg/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.layout import cmake_layout
from conan.tools.cmake import CMake
import os

required_conan_version = ">=1.50.0"

class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain"
test_type = "explicit"

def layout(self):
cmake_layout(self)

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

def build(self):
if can_run(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")
26 changes: 26 additions & 0 deletions recipes/bimg/all/test_package/test_package.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <bx/bx.h>
#include <bx/allocator.h>
#include <bimg/bimg.h>
#include <bimg/decode.h>

//An embedded 2x2 PNG image in RGB8 format with a red pixel, a green pixel, a blue pixel and a white pixel
const unsigned char img[129] ={0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x02, 0x08, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xd4, 0x9a,
0x73, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce,
0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00,
0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48,
0x59, 0x73, 0x00, 0x00, 0x0e, 0xc3, 0x00, 0x00, 0x0e, 0xc3, 0x01, 0xc7,
0x6f, 0xa8, 0x64, 0x00, 0x00, 0x00, 0x16, 0x49, 0x44, 0x41, 0x54, 0x18,
0x57, 0x63, 0x78, 0x2b, 0xa3, 0xa2, 0xb4, 0xd1, 0x87, 0xc1, 0xde, 0xe3,
0xcc, 0xff, 0xff, 0xff, 0x01, 0x24, 0xec, 0x06, 0x9d, 0x64, 0xf4, 0x18,
0xdc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};

int main() {
bx::DefaultAllocator defAlloc;
bimg::ImageContainer* imageContainer = nullptr;
imageContainer = bimg::imageParse(&defAlloc, (const void*) img, 129 * sizeof(char));
BX_ASSERT(imageContainer->m_format == bimg::TextureFormat::RGB8, "Image incorrectly decoded.")
bimg::imageFree(imageContainer);
return 0;
}
9 changes: 9 additions & 0 deletions recipes/bimg/all/test_v1_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.8)

project(test_package LANGUAGES CXX)

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

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)
17 changes: 17 additions & 0 deletions recipes/bimg/all/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from conans import ConanFile, CMake, tools
import os


class BimgTestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake", "cmake_find_package_multi"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
3 changes: 3 additions & 0 deletions recipes/bimg/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
versions:
"cci.20230114":
folder: all

0 comments on commit 1f36ae8

Please sign in to comment.