foobinding
CMakeLists.txt 文件内容
project(foobinding) cmake_minimum_required(VERSION 2.6) find_package(PythonLibs REQUIRED) find_package(Shiboken REQUIRED) find_program(GENERATOR generatorrunner REQUIRED) if (NOT GENERATOR) message(FATAL_ERROR "You need to specify GENERATOR variable (-DGENERATOR=value)") endif() if(CMAKE_HOST_UNIX) option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library size and performance. Only available on Release Mode" 0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") set(CMAKE_CXX_FLAGS_DEBUG "-g") if(ENABLE_GCC_OPTIMIZATION) set(CMAKE_BUILD_TYPE Release) set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -Os -Wl,-O1") if(NOT CMAKE_HOST_APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--hash-style=gnu") endif() endif() endif() enable_testing() add_subdirectory(foo) add_subdirectory(tests)内容本身是简单的,就是
查找python和shiboken的开发包 查找可执行程序generatorrunner 加入两个子目录只是中间加入的那堆优化选项是文件看起来很乱
foo这才是我们最重要的部分,先看CMakeLists.txt文件:
project(foo) set(foo_SRC ${CMAKE_CURRENT_BINARY_DIR}/foo/foo_module_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo/math_wrapper.cpp ) set(foo_INCLUDE_DIRECTORIES ${SHIBOKEN_INCLUDE_DIR} ${PYTHON_INCLUDE_PATH} ${libfoo_SOURCE_DIR} ) set(foo_LINK_LIBRARIES ${SHIBOKEN_PYTHON_LIBRARIES} ${SHIBOKEN_LIBRARY} libfoo ) include_directories(foo ${foo_INCLUDE_DIRECTORIES}) add_library(foo MODULE ${foo_SRC}) set_property(TARGET foo PROPERTY PREFIX "") if(WIN32) set_property(TARGET foo PROPERTY SUFFIX ".pyd") endif() target_link_libraries(foo ${foo_LINK_LIBRARIES}) add_custom_command(OUTPUT ${foo_SRC} COMMAND ${GENERATOR} --generatorSet=shiboken ${CMAKE_CURRENT_SOURCE_DIR}/global.h --include-paths=${libfoo_SOURCE_DIR} --output-directory=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_foo.xml WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for libfoo..." )难点就是生成胶水代码(这儿的custom命令):
它需要一个输入的 global.h 文件和 typesystem_foo.xml 文件 通过 --include-paths 指定global.h中包含的头文件所在的路径看一下这两个简单的文件:
global.h #include "foo.h" typesystem_foo.xml <?xml version="1.0"?> <typesystem package="foo"> <primitive-type/> <value-type/> </typesystem> tests生成东西能否工作呢?需要测试来说话:
CMakeLists.txt if(WIN32) set(TEST_PYTHONPATH "${foo_BINARY_DIR}") set(TEST_LIBRARY_PATH "${libfoo_BINARY_DIR};$ENV{PATH}") set(LIBRARY_PATH_VAR "PATH") string(REPLACE "\\" "/" TEST_PYTHONPATH "${TEST_PYTHONPATH}") string(REPLACE "\\" "/" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") string(REPLACE ";" "\\;" TEST_PYTHONPATH "${TEST_PYTHONPATH}") string(REPLACE ";" "\\;" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") else() set(TEST_PYTHONPATH "${foo_BINARY_DIR}") set(TEST_LIBRARY_PATH "${libfoo_BINARY_DIR}:$ENV{LD_LIBRARY_PATH}") set(LIBRARY_PATH_VAR "LD_LIBRARY_PATH") endif() add_test(math ${SHIBOKEN_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/test_foo.py) set_tests_properties(math PROPERTIES ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH}") 呵呵,这个文件看起来真烦!! 概念上还算简单的东西: 调用python来执行我们的测试程序 告诉python我们的绑定在那么路径下(通过环境变量PYTHONPATH) 告诉python去哪儿找需要的动态库(环境变量Unix下LD_LIBRARY_PATH,win下PATH) windows下需要对路径分隔符进行调整(烦)至于我们的测试程序,test_foo.py:
# -*- coding: utf-8 -*- import unittest import foo class MathTest(unittest.TestCase): def testMath(self): '''Test case for Math class from foo module.''' val = 5 math = foo.Math() self.assertEqual(math.squared(5), 5 * 5) if __name__ == '__main__': unittest.main()至此,所有代码看完了。环境准备好,编译就比较简单了,无非
mkdir build cd build cmake .. make make test