New build backend based on scikit-build-core

This commit is contained in:
Romain Thomas
2023-11-04 04:06:51 +01:00
parent 9961f6629d
commit 78006bc772
25 changed files with 615 additions and 699 deletions
+2 -9
View File
@@ -1,9 +1,6 @@
name: 'iOS'
on: push
env:
python-version: '3.10'
jobs:
ios-sdk:
runs-on: macos-11.0
@@ -11,14 +8,9 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ env.python-version }}
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
- name: Get Date
id: get-date
run: |
@@ -80,7 +72,8 @@ jobs:
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
liefproject/deploy \
python3 /src/.github/deploy.py /runner_tmp/artifacts
+8 -14
View File
@@ -72,7 +72,6 @@ jobs:
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
- name: Get Date
id: get-date
run: |
@@ -92,12 +91,13 @@ jobs:
- name: Upgrade pip
shell: bash
run: |
python -m pip install --upgrade pip setuptools
python -m pip install --upgrade pip
- name: Build Python 3.10 with tests
shell: bash
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
LIEF_BUILD_DIR: "/tmp/lief-build"
PYLIEF_CONF: "${{ github.workspace }}/scripts/osx/osx-testing-x64.toml"
MACOSX_TARGET: "11.7"
MACOSX_DEPLOYMENT_TARGET: "11.0"
CCACHE_DIR: ${{ runner.temp }}/.ccache
@@ -106,14 +106,11 @@ jobs:
CCACHE_COMPRESS: 1
run: |
python -m pip install -r tests/requirements.txt
python -m pip -vvv install api/python
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
cd api/python
PYLIEF_CONF=${GITHUB_WORKSPACE}/scripts/osx/osx-testing-x64.toml \
python -m pip -vvv install --user .
cd ${GITHUB_WORKSPACE}
python tests/run_pytest.py
python tests/run_tools_check.py ${LIEF_BUILD_DIR}/temp
ctest --output-on-failure --test-dir ${LIEF_BUILD_DIR}/temp
python tests/run_tools_check.py ${LIEF_BUILD_DIR}/
ctest --output-on-failure --test-dir ${LIEF_BUILD_DIR}/
wheels:
runs-on: macos-11.0
needs: osx-sdk
@@ -133,7 +130,7 @@ jobs:
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade pip
- name: Get Date
id: get-date
run: |
@@ -150,10 +147,6 @@ jobs:
key: osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}
- name: Upgrade pip
shell: bash
run: |
python -m pip install --upgrade pip setuptools
- name: Download LIEF install dir
uses: actions/download-artifact@v3
with:
@@ -206,6 +199,7 @@ jobs:
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
liefproject/deploy \
python3 /src/.github/deploy.py /runner_tmp/artifacts
+14 -16
View File
@@ -19,22 +19,20 @@ jobs:
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade pip
- name: Build with Python ${{ env.python-osx-version }} & Test
shell: bash
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
LIEF_BUILD_DIR: "/tmp/lief-build"
PYLIEF_CONF: "${{ github.workspace }}/scripts/osx/osx-testing-x64.toml"
run: |
python -m pip install -r tests/requirements.txt
python -m pip install -e api/python
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
cd api/python
PYLIEF_CONF=${GITHUB_WORKSPACE}/scripts/osx/osx-testing-x64.toml \
python -m pip install -e .
cd ${GITHUB_WORKSPACE}
python tests/run_pytest.py
python tests/run_tools_check.py ${BUILD_DIR}/temp
ctest --output-on-failure --test-dir ${BUILD_DIR}/temp
python tests/run_tools_check.py ${BUILD_DIR}
ctest --output-on-failure --test-dir ${BUILD_DIR}
linux:
runs-on: ubuntu-latest
steps:
@@ -46,11 +44,12 @@ jobs:
env:
PYTHON_VERSION: 39
run: |
docker run --rm \
-e PYTHON_VERSION=$PYTHON_VERSION \
docker run --rm \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-v $GITHUB_WORKSPACE:/src \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/test-linux-x64
-v $GITHUB_WORKSPACE:/src \
liefproject/manylinux_2_28_x86_64 \
bash /src/scripts/docker/test-linux-x64
windows:
runs-on: windows-latest
steps:
@@ -63,10 +62,10 @@ jobs:
- name: Install system dependencies
run: |
choco install ninja
python -m pip install --upgrade pip setuptools
python -m pip install --upgrade pip
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
vsversion: "2022"
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
@@ -76,15 +75,14 @@ jobs:
- name: Build Python ${{ env.python-win-version }}
run: |
python -m pip install -r tests/requirements.txt
python -m pip install api/python
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
cd api/python
python -m pip install -e .
shell: cmd
- name: Run tests
run: |
cd %GITHUB_WORKSPACE%
python tests/run_pytest.py
ctest --output-on-failure --test-dir %BUILD_DIR%/temp
ctest --output-on-failure --test-dir %BUILD_DIR%
shell: cmd
+3 -8
View File
@@ -132,14 +132,13 @@ jobs:
run: |
python -m pip install -r tests/requirements.txt
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
cd api/python
python -m pip -vvv install --user .
python -m pip -vvv install --user api/python
shell: cmd
- name: Run tests
run: |
cd %GITHUB_WORKSPACE%
python tests/run_pytest.py
ctest --output-on-failure --test-dir %LIEF_BUILD_DIR%/temp
ctest --output-on-failure --test-dir %LIEF_BUILD_DIR%/
shell: cmd
- name: sccache stats
run: sccache --show-stats
@@ -169,7 +168,7 @@ jobs:
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade pip
- uses: ilammy/msvc-dev-cmd@v1
with:
vsversion: "2022"
@@ -193,10 +192,6 @@ jobs:
path: ~/lief-${{ matrix.arch }}-install
- name: Start sccache server
run: sccache --start-server
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: Set arch specific env
if: matrix.arch == 'x64'
run: |
+2 -7
View File
@@ -34,7 +34,7 @@ jobs:
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade pip
- uses: ilammy/msvc-dev-cmd@v1
with:
vsversion: "2022"
@@ -57,16 +57,11 @@ jobs:
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: Build Python ${{ env.python-version }}
run: |
python -m pip install -r tests/requirements.txt
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
cd api/python
python -m pip -vvv install .
python -m pip -vvv install api/python
shell: cmd
- name: Run tests
run: |
-30
View File
@@ -41,36 +41,6 @@ project(LIEF VERSION
${LIEF_VERSION_MAJOR}.${LIEF_VERSION_MINOR}.${LIEF_VERSION_PATCH})
message(STATUS "${PROJECT_NAME} ${PROJECT_VERSION}")
# Select the MSVC runtime based on the LIEF_USE_CRT_XXX variable
if(MSVC)
foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
string(TOUPPER "${build_type}" build)
if(DEFINED "LIEF_USE_CRT_${build}")
set(runtime "${LIEF_USE_CRT_${build}}")
if(build_type STREQUAL Debug)
set(default_runtime MDd)
else()
set(default_runtime MD)
endif()
if(runtime AND NOT "${runtime}" STREQUAL "${default_runtime}")
if(runtime STREQUAL "MT")
set(runtime_library "MultiThreaded")
elseif(runtime STREQUAL "MD")
set(runtime_library "MultiThreadedDLL")
elseif(runtime STREQUAL "MTd")
set(runtime_library "MultiThreadedDebug")
elseif(runtime STREQUAL "MDd")
set(runtime_library "MultiThreadedDebugDLL")
else()
message(FATAL_ERROR "Unsupported value LIEF_USE_CRT_${build}=${runtime}")
endif()
message(STATUS "LIEF_CRT_${build}: ${runtime}")
set(CMAKE_MSVC_RUNTIME_LIBRARY "${CMAKE_MSVC_RUNTIME_LIBRARY}$<$<CONFIG:${build_type}>:${runtime_library}>")
endif()
endif()
endforeach()
endif()
# LIEF options
# =============
include(LIEFOptions)
+13 -60
View File
@@ -15,36 +15,20 @@ if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
include(ExternalProject)
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
macro(ADD_FLAG_IF_SUPPORTED flag name)
CHECK_C_COMPILER_FLAG("${flag}" "C_SUPPORTS_${name}")
CHECK_CXX_COMPILER_FLAG("${flag}" "CXX_SUPPORTS_${name}")
if (C_SUPPORTS_${name})
target_compile_options(pyLIEF PRIVATE ${flag})
endif()
if (CXX_SUPPORTS_${name})
target_compile_options(pyLIEF PRIVATE ${flag})
endif()
endmacro()
if (LIEF_EXTERNAL_NANOBINDS)
find_package(nanobind REQUIRED)
else()
set(NANOBIND_VERSION 1.7.0.r7.gfd1f04b)
set(NANOBIND_SHA256 SHA256=c6b1e0459559fc753ec6ef0911744f5fbc5f995e868dcb1ecef8f0c6c3d376d2)
set(NANOBIND_URL "${THIRD_PARTY_DIRECTORY}/nanobind-${NANOBIND_VERSION}.zip" CACHE STRING "URL to the Nanobind")
set(NANOBIND_URL "${THIRD_PARTY_DIRECTORY}/nanobind-${NANOBIND_VERSION}.zip"
CACHE STRING "URL to the Nanobind")
FetchContent_Declare(nanobind
URL ${NANOBIND_URL}
URL_HASH ${NANOBIND_SHA256}
)
FetchContent_Populate(nanobind)
find_package(nanobind REQUIRED PATHS ${nanobind_SOURCE_DIR}/cmake NO_DEFAULT_PATH)
find_package(nanobind REQUIRED PATHS ${nanobind_SOURCE_DIR}/cmake
NO_DEFAULT_PATH)
endif()
message(STATUS "Python version: ${Python_VERSION}")
@@ -60,18 +44,11 @@ set(LIEF_PYTHON_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyutils.cpp"
)
set(LIEF_PYTHON_HDR
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyErr.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pySafeString.hpp"
)
nanobind_add_module(
pyLIEF
NB_STATIC
${LIEF_PYTHON_SRC}
${LIEF_PYTHON_HDR}
# Do not default to -Os
NOMINSIZE
@@ -119,20 +96,18 @@ set_target_properties(pyLIEF PROPERTIES
CXX_VISIBILITY_PRESET hidden
C_VISIBILITY_PRESET hidden
PREFIX ""
OUTPUT_NAME "lief"
OUTPUT_NAME "_lief"
)
set_target_properties(pyLIEF PROPERTIES PYTHON_VERSION ${Python_VERSION})
target_link_libraries(pyLIEF PUBLIC ${LIEF_TARGET} lief_spdlog)
if(APPLE)
set_target_properties(pyLIEF PROPERTIES
MACOSX_RPATH ON
LINK_FLAGS "-undefined dynamic_lookup "
MACOSX_RPATH ON
LINK_FLAGS "-undefined dynamic_lookup "
)
endif()
set_target_properties(pyLIEF PROPERTIES PREFIX "")
if (UNIX)
# Even on osx (c.f. EXT_SUFFIX from sysconfig)
set_target_properties(pyLIEF PROPERTIES SUFFIX ".so")
@@ -140,36 +115,14 @@ elseif(WIN32)
set_target_properties(pyLIEF PROPERTIES SUFFIX ".pyd")
endif()
get_target_property(suffix pyLIEF SUFFIX)
set(LIEF_LIBRARY_NAME "lief${suffix}")
if (WIN32)
target_link_libraries(pyLIEF PUBLIC ${PYTHON_LIBRARIES})
endif()
if (CMAKE_BUILD_TYPE MATCHES Release AND UNIX AND NOT APPLE)
add_custom_command(TARGET pyLIEF
COMMENT "Strip LIEF Python bindings"
POST_BUILD
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:pyLIEF>
)
if(SKBUILD)
if(LIEF_PYTHON_EDITABLE)
install(TARGETS pyLIEF LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lief)
else()
install(TARGETS pyLIEF LIBRARY DESTINATION ${SKBUILD_PLATLIB_DIR}/lief/)
endif()
endif()
if (CMAKE_BUILD_TYPE MATCHES Release AND APPLE)
add_custom_command(TARGET pyLIEF
COMMENT "Strip LIEF Python bindings"
POST_BUILD
COMMAND ${CMAKE_STRIP} -x -S $<TARGET_FILE:pyLIEF>
)
endif()
add_custom_command(TARGET pyLIEF POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${PROJECT_BINARY_DIR}/api/python/lief
)
if (MSVC)
add_custom_command(TARGET pyLIEF POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${CMAKE_CURRENT_BINARY_DIR}
)
endif()
+224
View File
@@ -0,0 +1,224 @@
from __future__ import annotations
from pydantic_core import ErrorDetails
from pydantic import BaseModel, ValidationError, Field
from typing import Any, Optional, Union, List
from pathlib import Path
import tomli
import os
import platform
from scikit_build_core.settings.skbuild_read_settings import rich_print
def cmake_serialize(field: Any):
if isinstance(field, bool):
return "ON" if field else "OFF"
return field
class BuildConfig(BaseModel):
build_type: str = Field("Release", alias="type")
cache: bool = True
ninja: bool = False
default_target: str = Field("pyLIEF", alias="default-target")
parallel_jobs: int = Field(0, alias="parallel-jobs")
build_dir: Optional[str] = Field(None, alias="build-dir")
extra_targets: Union[List[str], str] = Field(None, alias="extra-targets")
extra_cmake: Union[List[str], str] = Field(None, alias="extra-cmake-opt")
lief_install_dir: Optional[str] = Field(None, alias="lief-install-dir")
py_api: str = Field("", alias="py-api")
@property
def targets(self) -> List[str]:
default_targets: List[str] = [self.default_target]
if self.extra_targets is not None:
if isinstance(self.extra_targets, str):
default_targets.append(self.extra_targets)
else:
default_targets.extend(self.extra_targets)
return default_targets
def cmake_dump(self) -> List[str]:
out: List[str] = [
f"-DLIEF_USE_CCACHE={cmake_serialize(self.cache)}"
]
if self.extra_cmake is not None:
if isinstance(self.extra_cmake, str):
out.append(self.extra_cmake)
elif isinstance(self.extra_cmake, list):
out.extend(self.extra_cmake)
if self.lief_install_dir is not None:
lief_cmake_dir = Path(self.lief_install_dir) / "share" / "LIEF" / "cmake"
lief_dir = lief_cmake_dir.expanduser().resolve().absolute()
out.extend((
"-DLIEF_PY_LIEF_EXT=on",
"-DLIEF_INSTALL=off",
f"-DLIEF_DIR={lief_dir.as_posix()}"
))
return out
class ThridParty(BaseModel):
spdlog: Optional[str] = None
def cmake_dump(self) -> List[str]:
out: List[str] = []
if self.spdlog is not None:
out.extend((
"-DLIEF_EXTERNAL_SPDLOG=ON",
f"-Dspdlog_DIR={self.spdlog}"
))
return out
class CrossCompilation(BaseModel):
osx_arch: Optional[str] = Field(None, alias="osx-arch")
platform: Optional[str] = None
def cmake_dump(self) -> List[str]:
out: List[str] = []
if self.osx_arch is not None:
out.extend((
f'-DCMAKE_OSX_ARCHITECTURES={self.osx_arch}',
))
return out
class Formats(BaseModel):
elf: bool = True
pe: bool = True
macho: bool = True
dex: bool = True
art: bool = True
oat: bool = True
vdex: bool = True
def cmake_dump(self) -> List[str]:
return [
f"-DLIEF_ELF={cmake_serialize(self.elf)}",
f"-DLIEF_PE={cmake_serialize(self.pe)}",
f"-DLIEF_MACHO={cmake_serialize(self.macho)}",
f"-DLIEF_DEX={cmake_serialize(self.dex)}",
f"-DLIEF_OAT={cmake_serialize(self.oat)}",
f"-DLIEF_ART={cmake_serialize(self.art)}",
f"-DLIEF_VDEX={cmake_serialize(self.vdex)}",
]
class Logging(BaseModel):
enabled: bool = True
debug: bool = False
def cmake_dump(self) -> List[str]:
return [
f"-DLIEF_LOGGING={cmake_serialize(self.enabled)}",
f"-DLIEF_LOGGING_DEBUG={cmake_serialize(self.debug)}",
]
class Features(BaseModel):
# json is an attribute already defined in BaseModel
json_support: bool = Field(True, alias="json")
frozen: bool = True
def cmake_dump(self) -> List[str]:
return [
f"-DLIEF_ENABLE_JSON={cmake_serialize(self.json_support)}",
f"-DLIEF_DISABLE_FROZEN={cmake_serialize(not self.frozen)}",
]
class ConfigT(BaseModel):
build: BuildConfig = BuildConfig()
formats: Formats = Formats()
third_party: ThridParty = Field(ThridParty(), alias="third-party")
features: Features = Features()
logging: Logging = Logging()
cross_compilation: CrossCompilation = Field(CrossCompilation(),
alias="cross-compilation")
def _cmake_base_args(self) -> List[str]:
return [
"-DLIEF_PYTHON_API=on",
"-DLIEF_INSTALL=off",
"-DLIEF_INSTALL_COMPILED_EXAMPLES=off",
]
def cmake_dump(self) -> List[str]:
return [
*self._cmake_base_args(),
*self.build.cmake_dump(),
*self.formats.cmake_dump(),
*self.third_party.cmake_dump(),
*self.features.cmake_dump(),
*self.logging.cmake_dump(),
*self.cross_compilation.cmake_dump(),
]
def pretty_error(err: ErrorDetails, file: Path):
loc = '.'.join(err['loc'])
if err['type'] == 'value_error.missing':
rich_print(f"[red]'{loc}' is missing in {file}")
else:
rich_print(f"[red]Error with '{loc}' in {file} ({err['msg']})")
class Config:
DEFAULT_EXCLUDE: List[str] = [
"*.so", "*.pyd"
]
def __init__(self, config: ConfigT):
self._config: ConfigT = config
@classmethod
def from_file(cls, file: Path):
with open(file, "rb") as f:
toml_config = tomli.load(f)
try:
return cls(ConfigT.model_validate(toml_config["lief"]))
except ValidationError as e:
for err in e.errors():
pretty_error(err, file)
return None
@property
def strip(self) -> str:
return str(self._config.build.build_type.lower() == "release")
@property
def build_dir(self) -> str:
if bdir := os.getenv("LIEF_BUILD_DIR", None):
return bdir
if bdir := self._config.build.build_dir:
return bdir
return ""
def get_cmake_args(self, editable: bool = False) -> List[str]:
cmake_args = self._config.cmake_dump()
if editable:
cmake_args.append(
"-DLIEF_PYTHON_EDITABLE=ON",
)
if self._config.build.ninja:
# For some reasons, this condition is not met:
# https://github.com/scikit-build/scikit-build-core/blob/9ac2e35aa888b70e9f1999a75dfafb7a5d709f88/src/scikit_build_core/cmake.py#L173-L174
# https://github.com/scikit-build/scikit-build-core/blob/9ac2e35aa888b70e9f1999a75dfafb7a5d709f88/src/scikit_build_core/cmake.py#L205-L207
cmake_args.append(
f"-DCMAKE_BUILD_TYPE={self._config.build.build_type}",
)
return cmake_args
@property
def cmake_generator(self) -> List[str]:
if self._config.build.ninja:
return ["-GNinja",]
return []
@property
def osx_arch(self) -> str:
return self.cross_compilation.osx_arch or platform.machine()
def __getattr__(self, name):
if value := getattr(self._config, name, None):
return value
return self.__getattribute__(name)
+14
View File
@@ -0,0 +1,14 @@
from __future__ import annotations
from pathlib import Path
from setup import ROOT_DIR
from versioning import Versioning
from scikit_build_core.settings.skbuild_read_settings import rich_print
def dynamic_metadata(field, config) -> str:
if field == "version":
version = Versioning().get_version()
rich_print(f"[green]LIEF Version: {version}")
return version
if field == "readme":
return (ROOT_DIR / "package" / "README.rst").as_posix()
+146
View File
@@ -0,0 +1,146 @@
from __future__ import annotations
from pathlib import Path
import os
import sys
import sysconfig
from functools import lru_cache
from typing import Optional, Union, List
CWD = Path(__file__).parent
ROOT_DIR = CWD / ".." / ".." / ".."
BINDING_DIR = ROOT_DIR / "api" / "python"
SRC_DIR = ROOT_DIR.resolve().absolute()
DEFAULT_CONF = CWD / ".." / "config-default.toml"
@lru_cache(maxsize=1)
def get_config():
from config import Config
if path := os.getenv("PYLIEF_CONF"):
config_path = Path(path).resolve().absolute()
return Config.from_file(config_path)
return Config.from_file(DEFAULT_CONF.as_posix())
def _fix_env():
config = get_config()
if sys.platform.startswith("win"):
if config.build.ninja:
from setuptools import msvc
is64 = sys.maxsize > 2**32
arch = 'x64' if is64 else 'x86'
ninja_env = msvc.msvc14_get_vc_env(arch)
os.environ.update(ninja_env)
if sys.platform.startswith("darwin"):
deployment_target = (
os.getenv("MACOSX_DEPLOYMENT_TARGET", None) or
sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")
)
os.environ["_PYTHON_HOST_PLATFORM"] = f"macosx-{deployment_target}-{config.osx_arch}"
# scikit_build_core is aware of ARCHFLAGS for the wheel arch:
# builder/builder.py:get_archs()
os.environ["ARCHFLAGS"]= f"-arch {config.osx_arch}"
if platform := config.cross_compilation.platform:
os.environ["_PYTHON_HOST_PLATFORM"] = platform
if os.name == 'nt' and platform == 'win32':
os.environ["VSCMD_ARG_TGT_ARCH"] = "x86"
sys.version = sys.version.lower().replace("amd64", "")
sys.platform = "win32"
def _get_hooked_config(is_editable: bool) -> Optional[dict[str, Union[str, List[str]]]]:
from config import Config
config = get_config()
if config is None:
raise RuntimeError("Can't get the configuration")
if config.build.py_api.startswith("cp3"):
# https://github.com/scikit-build/scikit-build-core/blob/9ac2e35aa888b70e9f1999a75dfafb7a5d709f88/src/scikit_build_core/builder/wheel_tag.py#L83-L85
# Make sure that this check is not silently warned since it could lead
# to a wrong .whl filename
minor = int(config.build.py_api[3:])
if (
sys.implementation.name != "cpython" or
minor > sys.version_info.minor
):
msg = f"Ignoring py-api, not a CPython interpreter ({sys.implementation.name}) or version (3.{minor}) is too high"
raise RuntimeError(msg)
config_settings = {
"logging.level": "DEBUG",
"build-dir": config.build_dir,
"install.strip": config.strip,
"backport.find-python": "0",
"wheel.py-api": config.build.py_api,
"cmake.source-dir": SRC_DIR.as_posix(),
"cmake.build-type": config.build.build_type,
"cmake.targets": config.build.targets,
"cmake.args": [
*config.cmake_generator,
*config.get_cmake_args(is_editable),
],
# 'wheel.exclude' does not exist but the 'wheel' is aware of it
# Note(romain): It could be worth to have a wheel.exclude for wheel.
# the directories in wheel.packages
"sdist.exclude": Config.DEFAULT_EXCLUDE,
}
return config_settings
def _get_build_requirements(is_editable: bool) -> List[str]:
build_req_file = BINDING_DIR / "build-requirements.txt"
reqs = [line for line in build_req_file.read_text().splitlines() if not line.startswith("#")]
return reqs
def get_requires_for_build_wheel(
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> list[str]:
return _get_build_requirements(is_editable=False)
def prepare_metadata_for_build_wheel(
metadata_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> str:
from scikit_build_core.build import prepare_metadata_for_build_wheel as _impl
_fix_env()
return _impl(metadata_directory, config_settings)
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
from scikit_build_core.build import build_wheel as _impl
config_settings = _get_hooked_config(is_editable=False)
_fix_env()
return _impl(wheel_directory, config_settings, metadata_directory)
def get_requires_for_build_editable(
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> List[str]:
return _get_build_requirements(is_editable=True)
def prepare_metadata_for_build_editable(
metadata_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> str:
from scikit_build_core.build import prepare_metadata_for_build_editable as _impl
_fix_env()
return _impl(metadata_directory, config_settings)
def build_editable(
wheel_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
metadata_directory: Optional[str] = None,
) -> str:
from scikit_build_core.build import build_editable as _impl
config_settings = _get_hooked_config(is_editable=True)
_fix_env()
return _impl(wheel_directory, config_settings, metadata_directory)
def build_sdist(
sdist_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> str:
raise RuntimeError("LIEF does not support Python source distribution ('sdist')")
+118
View File
@@ -0,0 +1,118 @@
from __future__ import annotations
import shlex
import subprocess
import re
import sys
from setup import ROOT_DIR
from scikit_build_core.settings.skbuild_read_settings import rich_print as _rich_print
from shutil import which
from typing import Optional
def rich_print(*args):
if sys.platform.startswith("win"):
# Workaround for:
# KeyError: 'WinError'
# File "[...]\scikit_build_core\_logging.py", line 122, in <genexpr>
# lambda m: "".join(colors()[x] for x in m.group(1).split()),
return print(*args)
return _rich_print(*args)
class Versioning:
COMMAND = '{git} describe --tags --long --dirty'
GIT_BRANCH = '{git} rev-parse --abbrev-ref HEAD'
IS_TAGGED_CMD = '{git} tag --list --points-at=HEAD'
FMT_DEV = '{tag}.dev0'
FMT_TAGGED = '{tag}'
CMAKE_VERSION_R = r"set\(LIEF_VERSION_(MAJOR|MINOR|PATCH)\s\"(\d+)\"\)"
def __init__(self):
self._git = which("git")
def _exec_git_cmd(self, cmd: str, **kwargs) -> str:
args = dict(kwargs)
args["git"] = self._git
cmd_list = shlex.split(cmd.format(**args))
return subprocess.check_output(cmd_list,
text=True,
cwd=ROOT_DIR.as_posix()).strip()
def has_git(self) -> bool:
return self._git is not None and (ROOT_DIR / ".git").is_dir()
def get_branch(self) -> Optional[str]:
if not self.has_git():
return None
try:
return self._exec_git_cmd(Versioning.GIT_BRANCH)
except subprocess.SubprocessError as e:
rich_print(f"[red]Error: {e}")
return None
def format_version(self, version: str, fmt: str, is_dev: bool = False):
branch = self.get_branch()
if branch is not None and branch.startswith("release-"):
_, version = branch.split("release-")
return version
parts = version.split('-')
assert len(parts) in (3, 4)
dirty = len(parts) == 4
tag, count, sha = parts[:3]
MA, MI, PA = map(int, tag.split(".")) # 0.9.0 -> (0, 9, 0)
if is_dev:
tag = f"{MA}.{MI + 1}.{0}"
if count == '0' and not dirty:
return tag
return fmt.format(tag=tag, gitsha=sha.lstrip('g'))
def version_from_git(self) -> Optional[str]:
if not self.has_git():
return None
try:
is_tagged = self._exec_git_cmd(Versioning.IS_TAGGED_CMD) != ""
git_version = self._exec_git_cmd(Versioning.COMMAND)
if is_tagged:
return self.format_version(version=git_version, fmt=Versioning.FMT_TAGGED)
return self.format_version(version=git_version, fmt=Versioning.FMT_DEV, is_dev=True)
except Exception as e:
rich_print(f"[red]Error: {e}")
return None
def version_from_cmake(self) -> Optional[str]:
main_cmake = ROOT_DIR / "CMakeLists.txt"
cmakefile = main_cmake.read_text()
major: Optional[int] = None
minor: Optional[int] = None
patch: Optional[int] = None
itre = re.finditer(Versioning.CMAKE_VERSION_R, cmakefile,
flags=re.MULTILINE)
for cmake_version in itre:
typ, value = cmake_version.groups()
typ = typ.lower()
if typ == "major":
major = int(value)
elif typ == "minor":
minor = int(value)
elif typ == "patch":
patch = int(value)
if any(e is None for e in (major, minor, patch)):
return None
return f"{major}.{minor}.{patch}"
def get_version(self) -> str:
if version := self.version_from_git():
return version
if version := self.version_from_cmake():
return version
raise RuntimeError("Can't determine version")
+12
View File
@@ -0,0 +1,12 @@
tomli==2.0.1
scikit-build-core==0.6.0
# For Ninja: msvc.msvc14_get_vc_env
setuptools==68.2.2
# For the "env" feature
pydantic==2.4.2
pydantic-core==2.10.1
# Implicit from scikit-build-core
pyproject_metadata==0.7.1
pathspec==0.11.2
build==1.0.3
wheel==0.41.3
+8 -2
View File
@@ -1,6 +1,7 @@
[build-system]
requires = ["setuptools", "wheel", "tomli"]
build-backend = "setuptools.build_meta"
requires = []
build-backend = "setup"
backend-path = ["backend"]
[project]
name = "lief"
@@ -19,6 +20,11 @@ classifiers = [
]
dynamic = ["version", "readme"]
[tool.scikit-build]
experimental = true
metadata.version.provider = "dynamic_provider"
metadata.readme.provider = "dynamic_provider"
[project.urls]
homepage = "https://lief-project.github.io/"
documentation = "https://lief-project.github.io/doc/latest/"
-501
View File
@@ -1,501 +0,0 @@
import os
import platform
import setuptools
import subprocess
import sys
import sysconfig
import tomli
from functools import lru_cache
from typing import List, Optional
from pathlib import Path
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext as _build_ext
from setuptools.command.build_py import build_py as _build_py
from setuptools.command.egg_info import egg_info as _egg_info
from setuptools.command.install_lib import install_lib as _install_lib
from setuptools.command.install_scripts import install_scripts as _install_scripts
from shutil import copy2, which
from tempfile import TemporaryDirectory
CURRENT_DIR = Path(__file__).parent
LIEF_DIR = (CURRENT_DIR / ".." / "..").absolute().resolve()
PACKAGE_NAME = "lief"
PYLIEF_CONF_ENV = "PYLIEF_CONF"
DEFAULT_TARGET = "pyLIEF"
ENV = os.environ
cmake_conf = None
def report(*args):
print(*args, file=sys.stderr)
class Config:
def __init__(self, config: dict):
self._config = config
if "cross-compilation" in self._config["lief"]:
cross_conf = self._config["lief"]["cross-compilation"]
if "platform" in cross_conf:
platform_build = cross_conf["platform"]
if os.name == "nt" and platform_build == "win32":
ENV["VSCMD_ARG_TGT_ARCH"] = "x86"
os.environ["VSCMD_ARG_TGT_ARCH"] = "x86"
@classmethod
def from_file(cls, file: Path):
with open(file, "rb") as f:
toml_config = tomli.load(f)
return cls(toml_config)
@staticmethod
def is_windows() -> bool:
return platform.system() == "Windows" and not sysconfig.get_platform().startswith("mingw")
def build_type(self) -> str:
return self._config['lief']['build']['type']
@property
@lru_cache(maxsize=1)
def build_root_dir(self):
if env_dir := os.getenv("LIEF_BUILD_DIR"):
return env_dir
return self._config['lief']['build'].get('dir', None)
def get_lief_format_opt(self):
opt = self._config["lief"]["formats"]
return (
"-DLIEF_ELF={}".format("ON" if opt["elf"] else "OFF"),
"-DLIEF_PE={}".format("ON" if opt["pe"] else "OFF"),
"-DLIEF_MACHO={}".format("ON" if opt["macho"] else "OFF"),
"-DLIEF_DEX={}".format("ON" if opt["dex"] else "OFF"),
"-DLIEF_ART={}".format("ON" if opt["art"] else "OFF"),
"-DLIEF_OAT={}".format("ON" if opt["oat"] else "OFF"),
"-DLIEF_VDEX={}".format("ON" if opt["vdex"] else "OFF"),
)
def get_lief_logging_opt(self):
opt = self._config["lief"]["logging"]
return (
"-DLIEF_LOGGING={}".format("ON" if opt["enabled"] else "OFF"),
"-DLIEF_LOGGING_DEBUG={}".format("ON" if opt["debug"] else "OFF"),
)
def get_python_opt(self):
config = ["-DLIEF_PYTHON_API=on"]
interpreter = Path(sys.executable)
base = sysconfig.get_config_var("installed_base")
if base is not None:
config += [f"-DPython_ROOT_DIR={base}"]
config += [
f"-DPython_EXECUTABLE={interpreter.as_posix()}",
]
return config
def get_generic_opt(self, output: str):
return (
f"-DCMAKE_BUILD_TYPE={self.build_type()}",
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={output}',
"-DLIEF_USE_CCACHE={}".format("ON" if self._config["lief"]["build"]["cache"] else "OFF"),
)
def get_feat_opt(self):
opt = self._config["lief"]["features"]
return (
"-DLIEF_ENABLE_JSON={}".format("ON" if opt["json"] else "OFF"),
"-DLIEF_DISABLE_FROZEN={}".format("OFF" if opt["frozen"] else "ON"),
)
def get_iwyu_opt(self):
if "include-what-you-use" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["include-what-you-use"]
return (f"-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE={value}", )
else:
return ("-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=''", )
def get_flags_opt(self):
opt = []
if "cxx-flags" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["cxx-flags"]
opt.append(f"-DCMAKE_CXX_FLAGS={value}")
else:
opt.append("-DCMAKE_CXX_FLAGS=''")
if "c-flags" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["c-flags"]
opt.append(f"-DCMAKE_C_FLAGS={value}")
else:
opt.append("-DCMAKE_C_FLAGS=''")
cxx_flags = os.getenv("CXXFLAGS", None)
c_flags = os.getenv("CFLAGS", None)
if cxx_flags is not None:
opt.append(f'-DCMAKE_CXX_FLAGS={cxx_flags}')
if c_flags is not None:
opt.append(f'-DCMAKE_C_FLAGS={c_flags}')
return opt
def get_cmake_extra_opt(self):
opt = []
if "extra-cmake-opt" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["extra-cmake-opt"]
if isinstance(value, str):
opt.append(value)
elif hasattr(value, "__iter__"):
opt.extend(value)
else:
print(f"Unsupported opt: {value} ({type(value)})")
sys.exit(1)
return opt
def get_third_party_opt(self) -> List[str]:
if "third-party" not in self._config["lief"]:
return []
cmake_opt = []
tp_conf = self._config["lief"]["third-party"]
if "spdlog" in tp_conf:
cmake_opt += [
"-DLIEF_EXTERNAL_SPDLOG=ON",
"-Dspdlog_DIR={}".format(tp_conf["spdlog"])
]
return cmake_opt
def get_cross_compile_opt(self) -> List[str]:
if "cross-compilation" not in self._config["lief"]:
return []
cmake_opt = []
cross_conf = self._config["lief"]["cross-compilation"]
if "osx-arch" in cross_conf:
cmake_opt += [
f'-DCMAKE_OSX_ARCHITECTURES={cross_conf["osx-arch"]}'
]
return cmake_opt
def get_pre_compile_opt(self):
install_path = self._config["lief"]["build"].get("lief-install-dir", None)
if install_path is None:
return []
install_path = Path(install_path).expanduser().resolve().absolute()
if not install_path.is_dir():
report(f"{install_path} is not a valid directory")
return []
cmake_dir = install_path / "share" / "LIEF" / "cmake"
if not (cmake_dir / "LIEFConfig.cmake").is_file():
report(f"Missing LIEFConfig.cmake in {cmake_dir}")
return []
return (
"-DLIEF_PY_LIEF_EXT=on",
"-DLIEF_INSTALL=off",
f"-DLIEF_DIR={cmake_dir}",
)
def gen_cmake_option(self, output: str) -> List[str]:
cfg = self.build_type()
opt = [
*self.get_generic_opt(output),
*self.get_python_opt(),
*self.get_lief_format_opt(),
*self.get_feat_opt(),
*self.get_iwyu_opt(),
*self.get_flags_opt(),
*self.get_third_party_opt(),
*self.get_pre_compile_opt(),
*self.get_cross_compile_opt(),
*self.get_cmake_extra_opt()
]
if self._use_ninja():
opt = ["-G", "Ninja"] + opt
if Config.is_windows():
is64 = sys.maxsize > 2**32
opt += [
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={output}',
f'-DLIEF_USE_CRT_{cfg.upper()}=MT',
]
if self._use_ninja():
from setuptools import msvc
arch = 'x64' if is64 else 'x86'
report(f"Arch: {arch}")
ninja_env = msvc.msvc14_get_vc_env(arch)
ENV.update(ninja_env)
else:
opt += ['-A', 'x64'] if is64 else ['-A', 'win32']
return opt
def _get_jobs(self) -> List[str]:
if "parallel-jobs" in self._config["lief"]["build"]:
jobs = self._config["lief"]["build"]["parallel-jobs"]
if jobs > 0:
return ["-j", str(jobs)]
return []
return []
def _get_targets(self) -> List[str]:
targets = [DEFAULT_TARGET]
if "extra-targets" in self._config["lief"]["build"]:
extra = self._config["lief"]["build"]["extra-targets"]
if isinstance(extra, str):
targets.append(extra)
elif hasattr(extra, "__iter__"):
targets.extend(extra)
else:
print(f"Unsupported opt: {targets} ({type(targets)})")
sys.exit(1)
return targets
def get_target_osx_arch(self) -> str:
if "cross-compilation" in self._config["lief"]:
cross_conf = self._config["lief"]["cross-compilation"]
if "osx-arch" in cross_conf:
arch = cross_conf["osx-arch"]
return arch
return platform.machine()
def _use_ninja(self) -> bool:
return self._config['lief']['build']['ninja']
def get_compile_cmd(self):
config = self._config['lief']['build']['type']
return [
'cmake',
'--build', '.',
'--target'] + self._get_targets() + [
'--config', config,
] + self._get_jobs()
@property
@lru_cache(maxsize=1)
def build_temp(self):
if build_dir := self.build_root_dir:
return (Path(build_dir) / "temp").as_posix()
return TemporaryDirectory(prefix="lief-temp-").name
@property
@lru_cache(maxsize=1)
def build_lib(self):
if build_dir := self.build_root_dir:
return (Path(build_dir) / "base").as_posix()
return TemporaryDirectory(prefix="lief-base-").name
class Versioning:
COMMAND = '{git} describe --tags --long --dirty'
GIT_BRANCH = '{git} rev-parse --abbrev-ref HEAD'
IS_TAGGED_CMD = '{git} tag --list --points-at=HEAD'
FMT_DEV = '{tag}.dev0'
FMT_TAGGED = '{tag}'
DEFAULT_VERSION = "0.14.0"
def __init__(self):
self._git = which("git")
def _exec_git_cmd(self, cmd: str, **kwargs) -> str:
args = dict(kwargs)
args["git"] = self._git
cmd_list = cmd.format(**args).split()
return subprocess.check_output(cmd_list).decode('utf-8').strip()
def has_git(self) -> bool:
return self._git is not None and (LIEF_DIR / ".git").is_dir()
def get_branch(self) -> Optional[str]:
if not self.has_git():
return None
try:
return self._exec_git_cmd(Versioning.GIT_BRANCH)
except subprocess.SubprocessError as e:
report(f"Error: {e}")
return None
def format_version(self, version: str, fmt: str, is_dev: bool = False):
branch = self.get_branch()
if branch is not None and branch.startswith("release-"):
_, version = branch.split("release-")
return version
parts = version.split('-')
assert len(parts) in (3, 4)
dirty = len(parts) == 4
tag, count, sha = parts[:3]
MA, MI, PA = map(int, tag.split(".")) # 0.9.0 -> (0, 9, 0)
if is_dev:
tag = f"{MA}.{MI + 1}.{0}"
if count == '0' and not dirty:
return tag
return fmt.format(tag=tag, gitsha=sha.lstrip('g'))
def version_from_git(self) -> str:
try:
is_tagged = self._exec_git_cmd(Versioning.IS_TAGGED_CMD) != ""
git_version = self._exec_git_cmd(Versioning.COMMAND)
if is_tagged:
return self.format_version(version=git_version, fmt=Versioning.FMT_TAGGED)
return self.format_version(version=git_version, fmt=Versioning.FMT_DEV, is_dev=True)
except Exception as e:
report(f"Error: {e}")
return Versioning.DEFAULT_VERSION
def get_version(self) -> str:
if self.has_git():
return self.version_from_git()
return Versioning.DEFAULT_VERSION
class LiefDistribution(setuptools.Distribution):
def __init__(self, attrs=None):
super().__init__(attrs)
class Module(Extension):
def __init__(self, name, sourcedir='', *args, **kwargs):
Extension.__init__(self, name, sources=[])
self.sourcedir = CURRENT_DIR.resolve().absolute().as_posix()
class build_ext(_build_ext):
def __init__(self, *args, **kwargs):
self._fix_platform()
super().__init__(*args, **kwargs)
def run(self):
for ext in self.extensions:
self.build_extension(ext)
if self.inplace:
self.copy_extensions_to_source()
def _fix_platform(self):
if sys.platform == "darwin":
deployment_target = os.getenv("MACOSX_DEPLOYMENT_TARGET", None)
machine = cmake_conf.get_target_osx_arch()
if deployment_target is None:
deployment_target = sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")
os.environ["_PYTHON_HOST_PLATFORM"] = f"macosx-{deployment_target}-{machine}"
report("Using platform: ", os.environ["_PYTHON_HOST_PLATFORM"])
else:
if "cross-compilation" in cmake_conf._config["lief"]:
cross_conf = cmake_conf._config["lief"]["cross-compilation"]
if "platform" in cross_conf:
platform = cross_conf["platform"]
os.environ["_PYTHON_HOST_PLATFORM"] = platform
ENV["_PYTHON_HOST_PLATFORM"] = platform
report("Using platform: ", platform)
if os.name == "nt" and platform == "win32":
self.plat_name = "win32"
version_fixed = sys.version.lower().replace("amd64", "")
sys.version = version_fixed
sys.platform = "win32"
def build_extension(self, ext):
self.build_lib = cmake_conf.build_lib
self.build_temp = cmake_conf.build_temp
build_temp = Path(self.build_temp)
build_lib = Path(self.build_lib)
cmake_output = build_temp.absolute()
cmake_bin = which("cmake")
if cmake_bin is None:
raise RuntimeError("Can't find cmake")
build_temp.mkdir(exist_ok=True, parents=True)
build_lib.mkdir(exist_ok=True, parents=True)
report(f"build-temp: {build_temp}")
report(f"build-lib: {build_lib}")
report(f"Platform : {platform.system()}")
report(f"Wheel library: {self.get_ext_fullname(ext.name)}")
cmake_subprocess_args = {
'cwd': build_temp.as_posix(),
'env': ENV,
}
# 1. Configure
configure_cmd = [
cmake_bin,
"-S", LIEF_DIR.as_posix(),
"-B", cmake_output.as_posix(),
] + cmake_conf.gen_cmake_option(cmake_output)
report("CMake Config:", " ".join(configure_cmd))
subprocess.check_call(configure_cmd, **cmake_subprocess_args)
compile_cmd = cmake_conf.get_compile_cmd()
report("Compile with:", " ".join(compile_cmd))
subprocess.check_call(compile_cmd, **cmake_subprocess_args)
pylief_dst = build_lib / self.get_ext_filename(self.get_ext_fullname(ext.name))
libsuffix = pylief_dst.suffix
pylief_path = cmake_output / f"{PACKAGE_NAME}{libsuffix}"
dst = Path(pylief_dst)
dst.parent.mkdir(exist_ok=True)
report(f"Copying {pylief_path} into {pylief_dst}")
if not self.dry_run:
copy2(pylief_path, pylief_dst)
class build_py(_build_py):
def finalize_options(self):
super().finalize_options()
self.build_lib = cmake_conf.build_lib
class install_lib(_install_lib):
def finalize_options(self):
super().finalize_options()
self.build_dir = cmake_conf.build_lib
class install_scripts(_install_scripts):
pass
class egg_info(_egg_info):
pass
versioning = Versioning()
version = versioning.get_version()
report(f"Version is: {version}")
conf_env = os.getenv(PYLIEF_CONF_ENV, None)
conf_file = CURRENT_DIR / "config-default.toml" if conf_env is None else Path(conf_env).absolute().resolve()
cmake_conf = Config.from_file(conf_file)
cmdclass = {
'build_ext': build_ext,
'build_py': build_py,
'egg_info': egg_info,
'install_lib': install_lib,
'install_scripts': install_scripts,
}
long_description = LIEF_DIR / "package" / "README.rst"
setup(
long_description=long_description.read_text(),
long_description_content_type="text/x-rst; charset=UTF-8",
distclass=LiefDistribution,
packages=["lief"],
package_data={"lief": ["py.typed", "*.pyi", "*.pyd"]},
ext_modules=[Module("lief._lief")],
cmdclass=cmdclass,
version=version
)
+4 -1
View File
@@ -17,7 +17,7 @@ option(LIEF_LOGGING_DEBUG "Enable debug logging"
option(LIEF_ENABLE_JSON "Enable JSON-related APIs" ON)
option(LIEF_OPT_NLOHMANN_JSON_EXTERNAL "Use nlohmann/json externaly" OFF)
option(LIEF_FORCE_API_EXPORTS "Force exports of API symbols" OFF)
option(LIEF_PY_LIEF_EXT "Use a pre-installed version of LIEF for the bindings" OFF)
option(LIEF_PY_LIEF_EXT "Use a pre-installed version of LIEF for the bindings" OFF)
option(LIEF_DISABLE_FROZEN "Disable Frozen even if it is supported" OFF)
@@ -28,6 +28,9 @@ option(LIEF_MACHO "Build LIEF with MachO module" ON)
option(LIEF_DEX "Build LIEF with DEX module" ON)
option(LIEF_ART "Build LIEF with ART module" ON)
cmake_dependent_option(LIEF_PYTHON_EDITABLE "Make an editable build " OFF
"LIEF_PYTHON_API" OFF)
# OAT support relies on the ELF and DEX format.
# Therefore, these options must be enabled to support use this format
cmake_dependent_option(LIEF_OAT "Build LIEF with OAT module" ON
+3 -3
View File
@@ -34,17 +34,17 @@ Libraries only (SDK)
.. warning::
On Windows one can choose the CRT to use by setting the ``LIEF_USE_CRT_<RELEASE;DEBUG;..>`` variable:
On Windows one can choose the CRT to use by setting the ``CMAKE_MSVC_RUNTIME_LIBRARY`` variable:
.. code-block:: console
$ cmake -DCMAKE_BUILD_TYPE=Release -DLIEF_USE_CRT_RELEASE=MT ..
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MT ..
For Debug, you should set the CRT to **MTd**:
.. code-block::
$ cmake -DCMAKE_BUILD_TYPE=Debug -DLIEF_USE_CRT_DEBUG=MTd ..
$ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MSVC_RUNTIME_LIBRARY=MTd ..
$ cmake --build . --target LIB_LIEF --config Debug
Python bindings
+9 -11
View File
@@ -1,15 +1,13 @@
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/cpp")
add_subdirectory(cpp)
if (LIEF_C_API)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/c")
add_subdirectory(c)
endif()
install(
DIRECTORY cmake
DESTINATION share/LIEF/examples
COMPONENT examples
)
if (LIEF_INSTALL)
install(
DIRECTORY cmake
DESTINATION share/LIEF/examples
COMPONENT examples
)
endif()
+8 -6
View File
@@ -61,10 +61,12 @@ endforeach()
endif()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/c
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|c)$"
)
if (LIEF_INSTALL)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/c
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|c)$"
)
endif()
@@ -14,7 +14,7 @@ option(LIEF_EXAMPLES "Build LIEF examples" OFF)
option(LIEF_TESTS "Build LIEF tests" OFF)
if(MSVC)
set(LIEF_USE_CRT_RELEASE "MT" CACHE STRING "LIEF CRT option")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MT" CACHE STRING "CRT option")
endif()
@@ -26,7 +26,7 @@ set(LIEF_CMAKE_ARGS
)
if(MSVC)
list(APPEND ${LIEF_CMAKE_ARGS} -DLIEF_USE_CRT_RELEASE=MT)
list(APPEND ${LIEF_CMAKE_ARGS} -DCMAKE_MSVC_RUNTIME_LIBRARY=MT)
endif()
ExternalProject_Add(LIEF
+8 -6
View File
@@ -140,11 +140,13 @@ foreach(example ${LIEF_CPP_EXAMPLES})
endforeach()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/cpp
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|cpp)$"
)
if (LIEF_INSTALL)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/cpp
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|cpp)$"
)
endif()
+5 -6
View File
@@ -5,19 +5,18 @@ export CXXFLAGS='-ffunction-sections -fdata-sections -fvisibility-inlines-hidden
export CFLAGS='-ffunction-sections -fdata-sections -static-libgcc'
export LDFLAGS='-Wl,--gc-sections'
export LIEF_BUILD_DIR=/tmp/lief-build
export _PYTHON_HOST_PLATFORM="manylinux2014-aarch64"
export SETUPTOOLS_EXT_SUFFIX=$($PYTHON_BINARY -c "import sysconfig;print(sysconfig.get_config_var('EXT_SUFFIX').replace('x86_64', 'aarch64'))")
export PYLIEF_CONF=/src/scripts/docker/config/pylinux-aarch64.toml
$PYTHON_BINARY -m venv /tmp/lief_venv
source /tmp/lief_venv/bin/activate
python -m pip install \
tomli==2.0.1 \
wheel==0.41.2 \
setuptools==68.2.2
python -m pip install -r /src/api/python/build-requirements.txt
pushd /src/api/python
# These exports need to set here to avoid pip install using the wrong platform
export _PYTHON_HOST_PLATFORM="manylinux2014-aarch64"
export SETUPTOOLS_EXT_SUFFIX=$($PYTHON_BINARY -c "import sysconfig;print(sysconfig.get_config_var('EXT_SUFFIX').replace('x86_64', 'aarch64'))")
python -m pip -vvv wheel \
--no-build-isolation \
--disable-pip-version-check \
+1 -5
View File
@@ -10,11 +10,7 @@ export LIEF_BUILD_DIR=/tmp/lief-build
$PYTHON_BINARY -m venv /tmp/lief_venv
source /tmp/lief_venv/bin/activate
python -m pip install \
tomli==2.0.1 \
wheel==0.41.2 \
setuptools==68.2.2
python -m pip install -r /src/api/python/build-requirements.txt
pushd /src/api/python
python -m pip -vvv wheel \
+9 -9
View File
@@ -11,35 +11,35 @@ export LIEF_BUILD_DIR="/tmp/lief-build"
$PYTHON_BINARY -m venv /tmp/lief_venv
source /tmp/lief_venv/bin/activate
python -m pip install -r /src/tests/requirements.txt
python -m pip install tomli pip wheel setuptools
python -m pip install \
-r /src/tests/requirements.txt \
-r /src/api/python/build-requirements.txt
mkdir -p ${LIEF_SAMPLES_DIR}
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
pushd /src/api/python
python -m pip -vvv wheel --no-build-isolation --wheel-dir=/src/wheel_stage .
python -m pip -vvv install .
popd
# Run the Python test suite
python tests/run_pytest.py
python tests/run_tools_check.py ${LIEF_BUILD_DIR}/temp
python tests/run_tools_check.py ${LIEF_BUILD_DIR}/
ctest --output-on-failure --test-dir ${LIEF_BUILD_DIR}/temp
ctest --output-on-failure --test-dir ${LIEF_BUILD_DIR}/
# Fuzzing
export PYTHONPATH="/src/tests:$PYTHONPATH"
python tests/elf/fuzzing.py \
${LIEF_BUILD_DIR}/temp/tests/Melkor/src/MELKOR/melkor \
${LIEF_BUILD_DIR}/tests/Melkor/src/MELKOR/melkor \
--input-seed ${LIEF_SAMPLES_DIR}/ELF/ELF64_x86-64_binary_ls.bin -n 100
python tests/elf/fuzzing.py \
${LIEF_BUILD_DIR}/temp/tests/Melkor/src/MELKOR/melkor \
${LIEF_BUILD_DIR}/tests/Melkor/src/MELKOR/melkor \
--input-seed ${LIEF_SAMPLES_DIR}/ELF/ELF64_x86-64_binary_openssl.bin -n 100
python tests/elf/fuzzing.py \
${LIEF_BUILD_DIR}/temp/tests/Melkor/src/MELKOR/melkor \
python tests/elf/fuzzing.py \
${LIEF_BUILD_DIR}/tests/Melkor/src/MELKOR/melkor \
--input-seed ${LIEF_SAMPLES_DIR}/ELF/ELF64_x86-64_binary_nm.bin -n 100
+2 -3
View File
@@ -49,22 +49,21 @@ cmake_config_static = [
"-G", "Ninja",
"-DCMAKE_BUILD_TYPE=Release",
"-DBUILD_SHARED_LIBS=off",
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MT",
"-DLIEF_PYTHON_API=off",
"-DLIEF_INSTALL_COMPILED_EXAMPLES=on",
"-DLIEF_USE_CRT_RELEASE=MT",
f"-DCMAKE_INSTALL_PREFIX={INSTALL_DIR.as_posix()}"
]
cmake_config_shared = [
"-G", "Ninja",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MT",
"-DBUILD_SHARED_LIBS=on",
"-DLIEF_PYTHON_API=off",
"-DLIEF_INSTALL_COMPILED_EXAMPLES=off",
"-DLIEF_USE_CRT_RELEASE=MT",
]
build_args = ['--config', 'Release']
configure_cmd = ['cmake', LIEF_SRC.resolve().as_posix()]