Skip to content

Commit 413e919

Browse files
committed
Start things off
0 parents  commit 413e919

File tree

7 files changed

+958
-0
lines changed

7 files changed

+958
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.vscode
2+
.kdev4
3+
*.kdev4
4+
5+
build
6+
build_*
7+
3rdparty
8+
9+
src/*.c

CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required( VERSION 3.1 )
2+
3+
project( blend2dpy C CXX )
4+
5+
# Blend2D
6+
# -------
7+
8+
set(CMAKE_CXX_STANDARD 17)
9+
10+
set(BLEND2D_DIR "${CMAKE_CURRENT_LIST_DIR}/../blend2d"
11+
CACHE PATH "Location of 'blend2d'")
12+
13+
set(BLEND2D_BUILD_STATIC TRUE)
14+
include("${BLEND2D_DIR}/CMakeLists.txt")
15+
16+
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(GNU|Clang|AppleClang)$")
17+
list(APPEND BLEND2D_CFLAGS "-fvisibility=hidden")
18+
endif()
19+
20+
# Blend2D Cython Extension
21+
# ------------------------
22+
23+
set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake )
24+
include( UseCython )
25+
26+
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/src )
27+
add_subdirectory( src )

cmake/FindCython.cmake

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Find the Cython compiler.
2+
#
3+
# This code sets the following variables:
4+
#
5+
# CYTHON_EXECUTABLE
6+
#
7+
# See also UseCython.cmake
8+
9+
#=============================================================================
10+
# Copyright 2011 Kitware, Inc.
11+
#
12+
# Licensed under the Apache License, Version 2.0 (the "License");
13+
# you may not use this file except in compliance with the License.
14+
# You may obtain a copy of the License at
15+
#
16+
# http://www.apache.org/licenses/LICENSE-2.0
17+
#
18+
# Unless required by applicable law or agreed to in writing, software
19+
# distributed under the License is distributed on an "AS IS" BASIS,
20+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21+
# See the License for the specific language governing permissions and
22+
# limitations under the License.
23+
#=============================================================================
24+
25+
# Use the Cython executable that lives next to the Python executable
26+
# if it is a local installation.
27+
find_package( PythonInterp )
28+
if( PYTHONINTERP_FOUND )
29+
get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH )
30+
find_program( CYTHON_EXECUTABLE
31+
NAMES cython cython.bat
32+
HINTS ${_python_path}
33+
)
34+
else()
35+
find_program( CYTHON_EXECUTABLE
36+
NAMES cython cython.bat
37+
)
38+
endif()
39+
40+
41+
include( FindPackageHandleStandardArgs )
42+
FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS CYTHON_EXECUTABLE )
43+
44+
mark_as_advanced( CYTHON_EXECUTABLE )
45+

cmake/UseCython.cmake

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
# Define a function to create Cython modules.
2+
#
3+
# For more information on the Cython project, see http://cython.org/.
4+
# "Cython is a language that makes writing C extensions for the Python language
5+
# as easy as Python itself."
6+
#
7+
# This file defines a CMake function to build a Cython Python module.
8+
# To use it, first include this file.
9+
#
10+
# include( UseCython )
11+
#
12+
# Then call cython_add_module to create a module.
13+
#
14+
# cython_add_module( <module_name> <src1> <src2> ... <srcN> )
15+
#
16+
# To create a standalone executable, the function
17+
#
18+
# cython_add_standalone_executable( <executable_name> [MAIN_MODULE src1] <src1> <src2> ... <srcN> )
19+
#
20+
# To avoid dependence on Python, set the PYTHON_LIBRARY cache variable to point
21+
# to a static library. If a MAIN_MODULE source is specified,
22+
# the "if __name__ == '__main__':" from that module is used as the C main() method
23+
# for the executable. If MAIN_MODULE, the source with the same basename as
24+
# <executable_name> is assumed to be the MAIN_MODULE.
25+
#
26+
# Where <module_name> is the name of the resulting Python module and
27+
# <src1> <src2> ... are source files to be compiled into the module, e.g. *.pyx,
28+
# *.py, *.c, *.cxx, etc. A CMake target is created with name <module_name>. This can
29+
# be used for target_link_libraries(), etc.
30+
#
31+
# The sample paths set with the CMake include_directories() command will be used
32+
# for include directories to search for *.pxd when running the Cython complire.
33+
#
34+
# Cache variables that effect the behavior include:
35+
#
36+
# CYTHON_ANNOTATE
37+
# CYTHON_NO_DOCSTRINGS
38+
# CYTHON_FLAGS
39+
#
40+
# Source file properties that effect the build process are
41+
#
42+
# CYTHON_IS_CXX
43+
#
44+
# If this is set of a *.pyx file with CMake set_source_files_properties()
45+
# command, the file will be compiled as a C++ file.
46+
#
47+
# See also FindCython.cmake
48+
49+
#=============================================================================
50+
# Copyright 2011 Kitware, Inc.
51+
#
52+
# Licensed under the Apache License, Version 2.0 (the "License");
53+
# you may not use this file except in compliance with the License.
54+
# You may obtain a copy of the License at
55+
#
56+
# http://www.apache.org/licenses/LICENSE-2.0
57+
#
58+
# Unless required by applicable law or agreed to in writing, software
59+
# distributed under the License is distributed on an "AS IS" BASIS,
60+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
61+
# See the License for the specific language governing permissions and
62+
# limitations under the License.
63+
#=============================================================================
64+
65+
# Configuration options.
66+
set( CYTHON_ANNOTATE OFF
67+
CACHE BOOL "Create an annotated .html file when compiling *.pyx." )
68+
set( CYTHON_NO_DOCSTRINGS OFF
69+
CACHE BOOL "Strip docstrings from the compiled module." )
70+
set( CYTHON_FLAGS "" CACHE STRING
71+
"Extra flags to the cython compiler." )
72+
mark_as_advanced( CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS )
73+
74+
find_package( Cython REQUIRED )
75+
find_package( PythonLibs REQUIRED )
76+
77+
set( CYTHON_CXX_EXTENSION "cxx" )
78+
set( CYTHON_C_EXTENSION "c" )
79+
80+
# Create a *.c or *.cxx file from a *.pyx file.
81+
# Input the generated file basename. The generate file will put into the variable
82+
# placed in the "generated_file" argument. Finally all the *.py and *.pyx files.
83+
function( compile_pyx _name generated_file )
84+
# Default to assuming all files are C.
85+
set( cxx_arg "" )
86+
set( extension ${CYTHON_C_EXTENSION} )
87+
set( pyx_lang "C" )
88+
set( comment "Compiling Cython C source for ${_name}..." )
89+
90+
set( cython_include_directories "" )
91+
set( pxd_dependencies "" )
92+
set( c_header_dependencies "" )
93+
set( pyx_locations "" )
94+
95+
foreach( pyx_file ${ARGN} )
96+
get_filename_component( pyx_file_basename "${pyx_file}" NAME_WE )
97+
98+
# Determine if it is a C or C++ file.
99+
get_source_file_property( property_is_cxx ${pyx_file} CYTHON_IS_CXX )
100+
if( ${property_is_cxx} )
101+
set( cxx_arg "--cplus" )
102+
set( extension ${CYTHON_CXX_EXTENSION} )
103+
set( pyx_lang "CXX" )
104+
set( comment "Compiling Cython CXX source for ${_name}..." )
105+
endif()
106+
107+
# Get the include directories.
108+
get_source_file_property( pyx_location ${pyx_file} LOCATION )
109+
get_filename_component( pyx_path ${pyx_location} PATH )
110+
get_directory_property( cmake_include_directories DIRECTORY ${pyx_path} INCLUDE_DIRECTORIES )
111+
list( APPEND cython_include_directories ${cmake_include_directories} )
112+
list( APPEND pyx_locations "${pyx_location}" )
113+
114+
# Determine dependencies.
115+
# Add the pxd file will the same name as the given pyx file.
116+
unset( corresponding_pxd_file CACHE )
117+
find_file( corresponding_pxd_file ${pyx_file_basename}.pxd
118+
PATHS "${pyx_path}" ${cmake_include_directories}
119+
NO_DEFAULT_PATH )
120+
if( corresponding_pxd_file )
121+
list( APPEND pxd_dependencies "${corresponding_pxd_file}" )
122+
endif()
123+
124+
# pxd files to check for additional dependencies.
125+
set( pxds_to_check "${pyx_file}" "${pxd_dependencies}" )
126+
set( pxds_checked "" )
127+
set( number_pxds_to_check 1 )
128+
while( ${number_pxds_to_check} GREATER 0 )
129+
foreach( pxd ${pxds_to_check} )
130+
list( APPEND pxds_checked "${pxd}" )
131+
list( REMOVE_ITEM pxds_to_check "${pxd}" )
132+
133+
# check for C header dependencies
134+
file( STRINGS "${pxd}" extern_from_statements
135+
REGEX "cdef[ ]+extern[ ]+from.*$" )
136+
foreach( statement ${extern_from_statements} )
137+
# Had trouble getting the quote in the regex
138+
string( REGEX REPLACE "cdef[ ]+extern[ ]+from[ ]+[\"]([^\"]+)[\"].*" "\\1" header "${statement}" )
139+
unset( header_location CACHE )
140+
find_file( header_location ${header} PATHS ${cmake_include_directories} )
141+
if( header_location )
142+
list( FIND c_header_dependencies "${header_location}" header_idx )
143+
if( ${header_idx} LESS 0 )
144+
list( APPEND c_header_dependencies "${header_location}" )
145+
endif()
146+
endif()
147+
endforeach()
148+
149+
# check for pxd dependencies
150+
151+
# Look for cimport statements.
152+
set( module_dependencies "" )
153+
file( STRINGS "${pxd}" cimport_statements REGEX cimport )
154+
foreach( statement ${cimport_statements} )
155+
if( ${statement} MATCHES from )
156+
string( REGEX REPLACE "from[ ]+([^ ]+).*" "\\1" module "${statement}" )
157+
else()
158+
string( REGEX REPLACE "cimport[ ]+([^ ]+).*" "\\1" module "${statement}" )
159+
endif()
160+
list( APPEND module_dependencies ${module} )
161+
endforeach()
162+
list( REMOVE_DUPLICATES module_dependencies )
163+
# Add the module to the files to check, if appropriate.
164+
foreach( module ${module_dependencies} )
165+
unset( pxd_location CACHE )
166+
find_file( pxd_location ${module}.pxd
167+
PATHS "${pyx_path}" ${cmake_include_directories} NO_DEFAULT_PATH )
168+
if( pxd_location )
169+
list( FIND pxds_checked ${pxd_location} pxd_idx )
170+
if( ${pxd_idx} LESS 0 )
171+
list( FIND pxds_to_check ${pxd_location} pxd_idx )
172+
if( ${pxd_idx} LESS 0 )
173+
list( APPEND pxds_to_check ${pxd_location} )
174+
list( APPEND pxd_dependencies ${pxd_location} )
175+
endif() # if it is not already going to be checked
176+
endif() # if it has not already been checked
177+
endif() # if pxd file can be found
178+
endforeach() # for each module dependency discovered
179+
endforeach() # for each pxd file to check
180+
list( LENGTH pxds_to_check number_pxds_to_check )
181+
endwhile()
182+
endforeach() # pyx_file
183+
184+
# Set additional flags.
185+
if( CYTHON_ANNOTATE )
186+
set( annotate_arg "--annotate" )
187+
endif()
188+
189+
if( CYTHON_NO_DOCSTRINGS )
190+
set( no_docstrings_arg "--no-docstrings" )
191+
endif()
192+
193+
if( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR
194+
"${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" )
195+
set( cython_debug_arg "--gdb" )
196+
endif()
197+
198+
# Include directory arguments.
199+
list( REMOVE_DUPLICATES cython_include_directories )
200+
set( include_directory_arg "" )
201+
foreach( _include_dir ${cython_include_directories} )
202+
set( include_directory_arg ${include_directory_arg} "-I" "${_include_dir}" )
203+
endforeach()
204+
205+
# Determining generated file name.
206+
set( _generated_file "${CMAKE_CURRENT_BINARY_DIR}/${_name}.${extension}" )
207+
set_source_files_properties( ${_generated_file} PROPERTIES GENERATED TRUE )
208+
set( ${generated_file} ${_generated_file} PARENT_SCOPE )
209+
210+
list( REMOVE_DUPLICATES pxd_dependencies )
211+
list( REMOVE_DUPLICATES c_header_dependencies )
212+
213+
# Add the command to run the compiler.
214+
add_custom_command( OUTPUT ${_generated_file}
215+
COMMAND ${CYTHON_EXECUTABLE}
216+
ARGS ${cxx_arg} ${include_directory_arg}
217+
${annotate_arg} ${no_docstrings_arg} ${cython_debug_arg} ${CYTHON_FLAGS}
218+
--output-file ${_generated_file} ${pyx_locations}
219+
DEPENDS ${pyx_locations} ${pxd_dependencies}
220+
IMPLICIT_DEPENDS ${pyx_lang} ${c_header_dependencies}
221+
COMMENT ${comment}
222+
)
223+
224+
# Remove their visibility to the user.
225+
set( corresponding_pxd_file "" CACHE INTERNAL "" )
226+
set( header_location "" CACHE INTERNAL "" )
227+
set( pxd_location "" CACHE INTERNAL "" )
228+
endfunction()
229+
230+
# cython_add_module( <name> src1 src2 ... srcN )
231+
# Build the Cython Python module.
232+
function( cython_add_module _name )
233+
set( pyx_module_sources "" )
234+
set( other_module_sources "" )
235+
foreach( _file ${ARGN} )
236+
if( ${_file} MATCHES ".*\\.py[x]?$" )
237+
list( APPEND pyx_module_sources ${_file} )
238+
else()
239+
list( APPEND other_module_sources ${_file} )
240+
endif()
241+
endforeach()
242+
compile_pyx( ${_name} generated_file ${pyx_module_sources} )
243+
include_directories( ${PYTHON_INCLUDE_DIRS} )
244+
python_add_module( ${_name} ${generated_file} ${other_module_sources} )
245+
if( APPLE )
246+
set_target_properties( ${_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
247+
else()
248+
target_link_libraries( ${_name} ${PYTHON_LIBRARIES} )
249+
endif()
250+
endfunction()
251+
252+
include( CMakeParseArguments )
253+
# cython_add_standalone_executable( _name [MAIN_MODULE src3.py] src1 src2 ... srcN )
254+
# Creates a standalone executable the given sources.
255+
function( cython_add_standalone_executable _name )
256+
set( pyx_module_sources "" )
257+
set( other_module_sources "" )
258+
set( main_module "" )
259+
cmake_parse_arguments( cython_arguments "" "MAIN_MODULE" "" ${ARGN} )
260+
include_directories( ${PYTHON_INCLUDE_DIRS} )
261+
foreach( _file ${cython_arguments_UNPARSED_ARGUMENTS} )
262+
if( ${_file} MATCHES ".*\\.py[x]?$" )
263+
get_filename_component( _file_we ${_file} NAME_WE )
264+
if( "${_file_we}" STREQUAL "${_name}" )
265+
set( main_module "${_file}" )
266+
elseif( NOT "${_file}" STREQUAL "${cython_arguments_MAIN_MODULE}" )
267+
set( PYTHON_MODULE_${_file_we}_static_BUILD_SHARED OFF )
268+
compile_pyx( "${_file_we}_static" generated_file "${_file}" )
269+
list( APPEND pyx_module_sources "${generated_file}" )
270+
endif()
271+
else()
272+
list( APPEND other_module_sources ${_file} )
273+
endif()
274+
endforeach()
275+
276+
if( cython_arguments_MAIN_MODULE )
277+
set( main_module ${cython_arguments_MAIN_MODULE} )
278+
endif()
279+
if( NOT main_module )
280+
message( FATAL_ERROR "main module not found." )
281+
endif()
282+
get_filename_component( main_module_we "${main_module}" NAME_WE )
283+
set( CYTHON_FLAGS ${CYTHON_FLAGS} --embed )
284+
compile_pyx( "${main_module_we}_static" generated_file ${main_module} )
285+
add_executable( ${_name} ${generated_file} ${pyx_module_sources} ${other_module_sources} )
286+
target_link_libraries( ${_name} ${PYTHON_LIBRARIES} ${pyx_module_libs} )
287+
endfunction()

src/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
if( NOT NUMPY_INCLUDE_DIR )
2+
find_package( PythonInterp )
3+
execute_process(
4+
COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print(numpy.get_include())"
5+
OUTPUT_VARIABLE _numpy_include
6+
OUTPUT_STRIP_TRAILING_WHITESPACE
7+
)
8+
find_path( NUMPY_INCLUDE_DIR numpy/arrayobject.h
9+
HINTS ${_numpy_include} )
10+
endif()
11+
12+
include_directories( ${NUMPY_INCLUDE_DIR} )
13+
14+
cython_add_module( capi capi.pyx )
15+
target_include_directories(capi BEFORE PRIVATE ${BLEND2D_INCLUDE_DIR})
16+
target_compile_options(capi PRIVATE ${BLEND2D_CFLAGS})
17+
target_link_libraries(capi ${BLEND2D_LIBS})

0 commit comments

Comments
 (0)