diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index a232058a13..b55c046949 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -47,6 +47,7 @@ UNIFY_ENVVARS_AND_CACHE(ICU_LIBRARY_DIR) UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_INCLUDE_DIR) UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_LIBRARY_DIR) UNIFY_ENVVARS_AND_CACHE(PCRE_LIBRARY_DIR) +UNIFY_ENVVARS_AND_CACHE(PYTHON_EXECUTABLE) # Find Boost IF(MSVC) @@ -274,25 +275,78 @@ if(NOT WIN32) INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} /usr/inc /usr/local/inc /usr/local/include/oce) endif() -IF(USE_IFC4) - ADD_DEFINITIONS(-DUSE_IFC4) - SET(IFC_RELEASE_NOT_USED "2x3") -ELSE() - ADD_DEFINITIONS(-DUSE_IFC2x3) # TODO Make all caps? i.e. USE_IFC2X3 - SET(IFC_RELEASE_NOT_USED "4") -ENDIF() +function(files_for_ifc_version IFC_VERSION RESULT_NAME) + set(IFC_PARSE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse) + set(${RESULT_NAME} + ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}.h + ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}enum.h + ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}-latebound.h + ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}.cpp + ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}-latebound.cpp + PARENT_SCOPE + ) +endfunction() + +if(COMPILE_SCHEMA) + set(IFC_RELEASE_NOT_USED "2x3" "4") + + if(PYTHON_EXECUTABLE) + set(PYTHON_EXECUTABLE_USED ${PYTHON_EXECUTABLE}) + else() + set(PYTHON_EXECUTABLE_USED "python") + endif() + + # Install pyparsing if necessary + execute_process(COMMAND ${PYTHON_EXECUTABLE_USED} -m pip "list" OUTPUT_VARIABLE PYTHON_PACKAGE_LIST) + string(FIND "${PYTHON_PACKAGE_LIST}" pyparsing PYPARSING_FOUND) + if ("${PYPARSING_FOUND}" STREQUAL "-1") + message(STATUS "Installing pyparsing") + execute_process(COMMAND ${PYTHON_EXECUTABLE_USED} -m pip "install" --user pyparsing) + else() + message(STATUS "Python interpreter with pyparsing found") + endif() + + # Bootstrap the parser + message(STATUS "Compiling schema, this will take a while...") + execute_process(COMMAND ${PYTHON_EXECUTABLE_USED} bootstrap.py express.bnf + WORKING_DIRECTORY ../src/ifcexpressparser + OUTPUT_FILE express_parser.py) + + # Generate code + execute_process(COMMAND ${PYTHON_EXECUTABLE_USED} ../ifcexpressparser/express_parser.py ../../${COMPILE_SCHEMA} + WORKING_DIRECTORY ../src/ifcparse + OUTPUT_VARIABLE COMPILED_SCHEMA_NAME) + + # Prevent the schema that had just been compiled from being excluded + if(${COMPILED_SCHEMA_NAME} STREQUAL "IFC2X3") + list(REMOVE_ITEM IFC_RELEASE_NOT_USED "2x3") + elseif(${COMPILED_SCHEMA_NAME} STREQUAL "IFC4") + list(REMOVE_ITEM IFC_RELEASE_NOT_USED "4") + endif() +else() + if(USE_IFC4) + add_definitions(-DUSE_IFC4) + set(IFC_RELEASE_NOT_USED "2x3") + else() + add_definitions(-DUSE_IFC2x3) # TODO Make all caps? i.e. USE_IFC2X3 + set(IFC_RELEASE_NOT_USED "4") + endif() +endif() # IfcParse file(GLOB CPP_FILES ../src/ifcparse/*.cpp) file(GLOB H_FILES ../src/ifcparse/*.h) set(SOURCE_FILES ${CPP_FILES} ${H_FILES}) -# Remove sources specific to an IFC release we are not using -list(REMOVE_ITEM SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse/Ifc${IFC_RELEASE_NOT_USED}.h) -list(REMOVE_ITEM SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse/Ifc${IFC_RELEASE_NOT_USED}enum.h) -list(REMOVE_ITEM SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse/Ifc${IFC_RELEASE_NOT_USED}-latebound.h) -list(REMOVE_ITEM SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse/Ifc${IFC_RELEASE_NOT_USED}.cpp) -list(REMOVE_ITEM SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse/Ifc${IFC_RELEASE_NOT_USED}-latebound.cpp) + +foreach(IFC_RELEASE ${IFC_RELEASE_NOT_USED}) + files_for_ifc_version(${IFC_RELEASE} SOURCE_FILES_NOT_USED) + foreach(SOURCE_FILE ${SOURCE_FILES_NOT_USED}) + list(REMOVE_ITEM SOURCE_FILES ${SOURCE_FILE}) + endforeach() +endforeach() + ADD_LIBRARY(IfcParse STATIC ${SOURCE_FILES}) + IF(UNICODE_SUPPORT) TARGET_LINK_LIBRARIES(IfcParse ${ICU_LIBRARIES}) ENDIF() diff --git a/src/ifcexpressparser/bootstrap.py b/src/ifcexpressparser/bootstrap.py index bb9e4a58e6..d59fe55048 100644 --- a/src/ifcexpressparser/bootstrap.py +++ b/src/ifcexpressparser/bootstrap.py @@ -184,4 +184,6 @@ enum_header.EnumHeader(mapping).emit() implementation.Implementation(mapping).emit() latebound_header.LateBoundHeader(mapping).emit() latebound_implementation.LateBoundImplementation(mapping).emit() + +sys.stdout.write(schema.name) """%('\n'.join(statements))) diff --git a/src/ifcexpressparser/documentation.py b/src/ifcexpressparser/documentation.py index e83bc132a8..ef8bde5a69 100644 --- a/src/ifcexpressparser/documentation.py +++ b/src/ifcexpressparser/documentation.py @@ -27,11 +27,15 @@ # # ############################################################################### -import re,csv +import re +import os import csv + try: from html.entities import entitydefs except: from htmlentitydefs import entitydefs +make_absolute = lambda fn: os.path.join(os.path.dirname(os.path.realpath(__file__)), fn) + name_to_oid = {} oid_to_desc = {} oid_to_name = {} @@ -39,6 +43,7 @@ oid_to_pid = {} regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' '])) definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv'] +definition_files = map(make_absolute, definition_files) for fn in definition_files: with open(fn) as f: for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'): @@ -46,11 +51,11 @@ for fn in definition_files: oid_to_name[oid] = name oid_to_desc[oid] = desc -with open('DocEntityAttributes.csv') as f: +with open(make_absolute('DocEntityAttributes.csv')) as f: for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'): oid_to_pid[oid] = pid -with open('DocAttribute.csv') as f: +with open(make_absolute('DocAttribute.csv')) as f: for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'): pid = oid_to_pid[oid] pname = oid_to_name[pid] diff --git a/win/run-cmake.bat b/win/run-cmake.bat index d9fb548743..c714b72484 100644 --- a/win/run-cmake.bat +++ b/win/run-cmake.bat @@ -56,6 +56,7 @@ if not defined PY_VER_MAJOR_MINOR set PY_VER_MAJOR_MINOR=34 if not defined PYTHONPATH set PYTHONPATH=%INSTALL_DIR%\Python%PY_VER_MAJOR_MINOR% set PYTHON_INCLUDE_DIR=%PYTHONPATH%\include set PYTHON_LIBRARY=%PYTHONPATH%\libs\python%PY_VER_MAJOR_MINOR%.lib +set PYTHON_EXECUTABLE=%PYTHONPATH%\python.exe set SWIG_DIR=%INSTALL_DIR%\swigwin set PATH=%PATH%;%SWIG_DIR%;%PYTHONPATH% :: TODO 3ds Max SDK? @@ -77,6 +78,7 @@ echo OPENCOLLADA_LIBRARY_DIR = %OPENCOLLADA_LIBRARY_DIR% echo PYTHONPATH = %PYTHONPATH% echo PYTHON_INCLUDE_DIR = %PYTHON_INCLUDE_DIR% echo PYTHON_LIBRARY = %PYTHON_LIBRARY% +echo PYTHON_EXECUTABLE = %PYTHON_EXECUTABLE% echo SWIG_DIR = %SWIG_DIR% echo. echo CMAKE_INSTALL_PREFIX = %CMAKE_INSTALL_PREFIX%