Skip to content
This repository has been archived by the owner on May 25, 2024. It is now read-only.

Commit

Permalink
build: refactor to use cmake to build package
Browse files Browse the repository at this point in the history
  • Loading branch information
Antares0982 committed Apr 27, 2024
1 parent 8379d6a commit 147fca1
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 64 deletions.
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.12)

project(pycjson C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 17)

find_package(Python3 COMPONENTS Development)

set(SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(DEPS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/deps)
file(GLOB_RECURSE SRC_C_FILES ${SRC_PATH}/*.c)
file(GLOB_RECURSE DEPS_CPP_FILES ${DEPS_PATH}/*.cpp)

add_library(cjson SHARED ${SRC_C_FILES} ${DEPS_CPP_FILES})
target_include_directories(cjson PUBLIC ${SRC_PATH} ${DEPS_PATH} ${Python3_INCLUDE_DIRS})
target_link_libraries(cjson ${Python3_LIBRARIES})
set_target_properties(cjson PROPERTIES PREFIX "")
set_target_properties(cjson PROPERTIES LINKER_LANGUAGE C)
21 changes: 21 additions & 0 deletions deps/dconv_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "double-conversion.hpp"

#include <Python.h>
#include <pymath.h>

using namespace double_conversion;

extern "C" {
int dconv_d2s(double value, char *buf, int buflen, int *strlength) {
static auto d2s = DoubleToStringConverter(DoubleToStringConverter::NO_FLAGS, "Infinity", "NaN", 'e', -324, 308, 0, 0);
StringBuilder sb(buf, buflen);
int success = d2s.ToShortest(value, &sb);
*strlength = success ? sb.position() : -1;
return success;
}

double dconv_s2d(const char *buffer, int length, int *processed_characters_count) {
static auto s2d = StringToDoubleConverter(StringToDoubleConverter::NO_FLAGS, 0.0, Py_NAN, "Infinity", "NaN");
return s2d.StringToDouble(buffer, length, processed_characters_count);
}
}
115 changes: 76 additions & 39 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,92 @@
import os
import platform
import subprocess
import sys

from setuptools import Extension, setup
from setuptools.command.build_ext import build_ext

CPPSTD = "c++2a"
CSTD = "c2x"
extra_compile_args = ["-D_GNU_SOURCE"]
if platform.system() == "Linux":
strip_flags = ["-Wl,--strip-all"]
extra_compile_args += [f"-std={CPPSTD}", f"-std={CSTD}"]
elif platform.system() == "Windows":
strip_flags = []
extra_compile_args += [f"/std:c++20", f"/std:c2x"]
elif platform.system() == "Darwin":
strip_flags = []
extra_compile_args += [f"-std=c++17"]


def find_src():
srcs = []
headers = []
for root, _, files in os.walk("src"):
for file in files:
if file.endswith(".c") or file.endswith(".cpp"):
srcs.append(os.path.join(root, file))
elif file.endswith(".h"):
if file != "version_template.h":
headers.append(os.path.join(root, file))
srcs.append(os.path.abspath("./deps/double-conversion.cpp"))
headers.append(os.path.abspath("./deps/double-conversion.hpp"))
return srcs, headers


srcs, headers = find_src()

module1 = Extension(
"cjson",
sources=srcs,
include_dirs=["./src", "./deps"],
extra_compile_args=extra_compile_args,
extra_link_args=["-lstdc++", "-lm"] + strip_flags,
)

with open("src/version_template.h", encoding='utf-8') as f:
version_template = f.read()


class CMakeExtension(Extension):
def __init__(self, name, cmake_lists_dir='.', **kwargs):
Extension.__init__(self, name, sources=[], **kwargs)
self.cmake_lists_dir = os.path.abspath(cmake_lists_dir)


class cmake_build_ext(build_ext):
def build_extensions(self):
# Ensure that CMake is present and working
try:
out = subprocess.check_output(['cmake', '--version'])
except OSError:
raise RuntimeError('Cannot find CMake executable')

for ext in self.extensions:

extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
# cfg = 'Debug' if options['--debug'] == 'ON' else 'Release'
cfg = 'Release'

cmake_args = [
f'-DCMAKE_BUILD_TYPE={cfg}',
# Ask CMake to place the resulting library in the directory
# containing the extension
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir),
# Other intermediate static libraries are placed in a
# temporary build directory instead
'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), self.build_temp),
# Hint CMake to use the same Python executable that
# is launching the build, prevents possible mismatching if
# multiple versions of Python are installed
'-DPYTHON_EXECUTABLE={}'.format(sys.executable),
# Add other project-specific CMake arguments if needed
# ...
]

# We can handle some platform-specific settings at our discretion
if platform.system() == 'Windows':
plat = ('x64' if platform.architecture()[0] == '64bit' else 'Win32')
cmake_args += [
# These options are likely to be needed under Windows
'-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE',
'-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir),
]
# Assuming that Visual Studio and MinGW are supported compilers
if self.compiler.compiler_type == 'msvc':
cmake_args += [
'-DCMAKE_GENERATOR_PLATFORM=%s' % plat,
]
else:
cmake_args += [
'-G', 'MinGW Makefiles',
]
# cmake_args += cmake_cmd_args

if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)

# Config
subprocess.check_call(['cmake', ext.cmake_lists_dir] + cmake_args,
cwd=self.build_temp)

# Build
subprocess.check_call(['cmake', '--build', '.', '--config', cfg],
cwd=self.build_temp)


setup(
ext_modules=[module1],
name='cjson',
use_scm_version={
"local_scheme": lambda x: "",
"write_to": "src/version.h",
"write_to_template": version_template,
},
ext_modules=[
CMakeExtension(name='cjson')
],
cmdclass=dict(build_ext=cmake_build_ext)
)
23 changes: 0 additions & 23 deletions src/dconv_wrapper.cpp

This file was deleted.

7 changes: 6 additions & 1 deletion src/dconv_wrapper.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#ifndef DCONV_WRAPPER_H
#define DCONV_WRAPPER_H

#ifdef __cplusplus
extern "C" {
#endif
int dconv_d2s(double value, char *buf, int buflen, int *strlength);

double dconv_s2d(const char *buffer, int length, int *processed_characters_count);

#ifdef __cplusplus
}
#endif
#endif //DCONV_WRAPPER_H
2 changes: 1 addition & 1 deletion src/pycJSON_decode.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "pycJSON.h"
#define PY_SSIZE_T_CLEAN
#include "pycJSON.h"
#include "dconv_wrapper.h"
#include <Python.h>
#include <math.h>
Expand Down

0 comments on commit 147fca1

Please sign in to comment.