From 084992ddcc880fd46ed9074f00602bdcf2cd271f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 12 Dec 2025 12:19:40 +0500 Subject: [PATCH] Make IfcParseExamples buildable outside of the main build tree It's a very verbose version of consuming IfcOpenShell cmake package, but we'll be able to use it as a start point to build upon. --- .github/workflows/ci.yml | 33 +++++++++ .gitignore | 1 + src/examples/CMakeLists.txt | 62 +++++++++++----- src/examples/IfcParseExamples_test.ifc | 97 ++++++++++++++++++++++++++ src/examples/README.md | 22 ++++++ 5 files changed, 198 insertions(+), 17 deletions(-) create mode 100644 src/examples/IfcParseExamples_test.ifc create mode 100644 src/examples/README.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 677a0cfde3..afdbc4d6fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,31 @@ jobs: -DCMAKE_CXX_FLAGS_INIT="-fPIC" sudo make -j$(nproc) install + # We need zstd and libxml2 just for cmake config files to test the examples build. + # zslibzstd-dev has cmake config only on Ubuntu 24.04+. + - name : Build zstd + run: | + git clone https://github.com/facebook/zstd --depth 1 --branch v1.5.7 + cd zstd + # `build` already exists. + mkdir build_ && cd build_ + cmake ../build/cmake -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + sudo cmake --build . --target install -j $(nproc) + + # libxml2-dev doesn't have cmake configs even on Ubuntu 24.04+. + - name: Build libxml2 + run: | + git clone https://gitlab.gnome.org/GNOME/libxml2.git --branch v2.13.8 --depth 1 + cd libxml2 + mkdir build && cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + sudo cmake --build . --target install -j $(nproc) + # Ubuntu has `swig` package, but we build it to match the version we use in the main build. # To avoid failing tests when checking stub generation. - name: build swig @@ -178,6 +203,14 @@ jobs: run: | IfcConvert test/input/acad2010_walls.ifc test/input/acad2010_walls.obj + - name: Build standalone examples to test cmake package + run: | + cd src/examples + mkdir build && cd build + cmake .. -DCMAKE_BUILD_TYPE=Release + cmake --build . + ./IfcParseExamples "../IfcParseExamples_test.ifc" + - name: Test ifcopenshell-python run: | cd test diff --git a/.gitignore b/.gitignore index 504685d332..bfdfdd5f76 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /_deps-vs*-x*-installed/ /_installed-vs*-x*/ /build/ +/src/examples/build/ # output directories /cmake/out/ diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 1bdad7f032..809e4bccdf 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -17,31 +17,59 @@ # # ################################################################################ -if(SCHEMA_VERSIONS MATCHES "2x3") - ADD_EXECUTABLE(IfcParseExamples IfcParseExamples.cpp) - TARGET_LINK_LIBRARIES(IfcParseExamples IfcParse) - set_target_properties(IfcParseExamples PROPERTIES FOLDER Examples) - target_compile_features(IfcParseExamples PUBLIC cxx_std_17) +# Thils file can also be build standalone, outside of the IfcOpenShell build tree, +# to demonstrate the usage IfcOpenShell as a cmake package. +if(NOT BUILD_EXAMPLES) + set(STANDALONE_PROJECT ON) +endif() - if(WITH_OPENCASCADE) +if(STANDALONE_PROJECT) + cmake_minimum_required(VERSION 3.21) + project(IfcOpenShellExamples) - ADD_EXECUTABLE(IfcOpenHouse IfcOpenHouse.cpp) - TARGET_LINK_LIBRARIES(IfcOpenHouse ${IFCOPENSHELL_LIBRARIES} ${OpenCASCADE_LIBRARIES}) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_STATIC_RUNTIME OFF) + set(Boost_USE_MULTITHREADED ON) + set(Boost_COMPONENTS system program_options regex thread date_time iostreams) + find_package(Boost CONFIG REQUIRED COMPONENTS ${Boost_COMPONENTS}) + find_package(zstd CONFIG REQUIRED) + find_package(RocksDB CONFIG REQUIRED) + find_package(LibXml2 CONFIG REQUIRED) + find_package(IfcOpenShell CONFIG REQUIRED) +endif() + +if(STANDALONE_PROJECT OR SCHEMA_VERSIONS MATCHES "2x3") + add_executable(IfcParseExamples IfcParseExamples.cpp) + + if(STANDALONE_PROJECT) + target_include_directories(IfcParseExamples PRIVATE ${Boost_INCLUDE_DIRS}) + target_link_libraries(IfcParseExamples ${Boost_LIBRARIES}) + target_link_libraries(IfcParseExamples IfcOpenShell::IfcParse) + target_compile_features(IfcParseExamples PRIVATE cxx_std_17) + target_compile_definitions(IfcParseExamples PRIVATE "SCHEMA_SEQ=(2x3)" HAS_SCHEMA_2x3 IFOPSH_WITH_ROCKSDB) + else() + target_link_libraries(IfcParseExamples IfcParse) + set_target_properties(IfcParseExamples PROPERTIES FOLDER Examples) + target_compile_features(IfcParseExamples PRIVATE cxx_std_17) + endif() + + if(NOT STANDALONE_PROJECT AND WITH_OPENCASCADE) + add_executable(IfcOpenHouse IfcOpenHouse.cpp) + target_link_libraries(IfcOpenHouse ${IFCOPENSHELL_LIBRARIES} ${OpenCASCADE_LIBRARIES}) set_target_properties(IfcOpenHouse PROPERTIES FOLDER Examples) - ADD_EXECUTABLE(IfcAdvancedHouse IfcAdvancedHouse.cpp) - TARGET_LINK_LIBRARIES(IfcAdvancedHouse ${IFCOPENSHELL_LIBRARIES} ${OpenCASCADE_LIBRARIES}) + add_executable(IfcAdvancedHouse IfcAdvancedHouse.cpp) + target_link_libraries(IfcAdvancedHouse ${IFCOPENSHELL_LIBRARIES} ${OpenCASCADE_LIBRARIES}) set_target_properties(IfcAdvancedHouse PROPERTIES FOLDER Examples) - endif() -endif(SCHEMA_VERSIONS MATCHES "2x3") +endif() -if(SCHEMA_VERSIONS MATCHES "4x3_add2") - ADD_EXECUTABLE(IfcAlignment IfcAlignment.cpp) - TARGET_LINK_LIBRARIES(IfcAlignment ${IFCOPENSHELL_LIBRARIES}) +if(NOT STANDALONE_PROJECT AND SCHEMA_VERSIONS MATCHES "4x3_add2") + add_executable(IfcAlignment IfcAlignment.cpp) + target_link_libraries(IfcAlignment ${IFCOPENSHELL_LIBRARIES}) set_target_properties(IfcAlignment PROPERTIES FOLDER Examples) - ADD_EXECUTABLE(IfcSimplifiedAlignment IfcSimplifiedAlignment.cpp) - TARGET_LINK_LIBRARIES(IfcSimplifiedAlignment ${IFCOPENSHELL_LIBRARIES}) + add_executable(IfcSimplifiedAlignment IfcSimplifiedAlignment.cpp) + target_link_libraries(IfcSimplifiedAlignment ${IFCOPENSHELL_LIBRARIES}) set_target_properties(IfcSimplifiedAlignment PROPERTIES FOLDER Examples) endif() diff --git a/src/examples/IfcParseExamples_test.ifc b/src/examples/IfcParseExamples_test.ifc new file mode 100644 index 0000000000..9fec9e76b4 --- /dev/null +++ b/src/examples/IfcParseExamples_test.ifc @@ -0,0 +1,97 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1'); +FILE_NAME('IfcParseExamples_test.ifc','2025-12-12T13:49:19+05:00',(''),(''),'IfcOpenShell 0.0.0','Bonsai 0.8.5-alpha251212-a47cbc3','Nobody'); +FILE_SCHEMA(('IFC2X3')); +ENDSEC; +DATA; +#1=IFCPERSON('HSeldon','Seldon','Hari',$,$,$,$,$); +#2=IFCORGANIZATION('APTR','Aperture Science',$,$,$); +#3=IFCPERSONANDORGANIZATION(#1,#2,$); +#4=IFCACTORROLE(.USERDEFINED.,'CONTRIBUTOR',$); +#5=IFCORGANIZATION('IfcOpenShell','IfcOpenShell','IfcOpenShell is an open source software library that helps users and software developers to work with IFC data.',(#4),(#6)); +#6=IFCTELECOMADDRESS(.USERDEFINED.,$,'WEBPAGE',$,$,$,$,'https://ifcopenshell.org'); +#7=IFCAPPLICATION(#5,'0.8.5','Bonsai','Bonsai-0.8.5'); +#8=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605); +#9=IFCPROJECT('3GSSvm5SP5U96O5iar8uYb',#8,'My Project',$,$,$,$,(#22,#34),#17); +#10=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.); +#11=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#12=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#13=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0); +#14=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#15=IFCMEASUREWITHUNIT(IFCREAL(0.0174532925199433),#14); +#16=IFCCONVERSIONBASEDUNIT(#13,.PLANEANGLEUNIT.,'degree',#15); +#17=IFCUNITASSIGNMENT((#12,#10,#16,#11)); +#18=IFCCARTESIANPOINT((0.,0.,0.)); +#19=IFCDIRECTION((0.,0.,1.)); +#20=IFCDIRECTION((1.,0.,0.)); +#21=IFCAXIS2PLACEMENT3D(#18,#19,#20); +#22=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#21,$); +#23=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$); +#24=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Axis','Model',*,*,*,*,#22,$,.GRAPH_VIEW.,$); +#25=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Box','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$); +#26=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.SECTION_VIEW.,$); +#27=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.ELEVATION_VIEW.,$); +#28=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$); +#29=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.PLAN_VIEW.,$); +#30=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Profile','Model',*,*,*,*,#22,$,.ELEVATION_VIEW.,$); +#31=IFCCARTESIANPOINT((0.,0.)); +#32=IFCDIRECTION((1.,0.)); +#33=IFCAXIS2PLACEMENT2D(#31,#32); +#34=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Plan',2,1.E-05,#33,$); +#35=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Axis','Plan',*,*,*,*,#34,$,.GRAPH_VIEW.,$); +#36=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Plan',*,*,*,*,#34,$,.PLAN_VIEW.,$); +#37=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Plan',*,*,*,*,#34,$,.PLAN_VIEW.,$); +#38=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Plan',*,*,*,*,#34,$,.REFLECTED_PLAN_VIEW.,$); +#39=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605); +#40=IFCSITE('2Ys4j4OOf3x9UYeALDJ_g3',#39,'My Site',$,$,#66,$,$,.ELEMENT.,$,$,$,$,$); +#46=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605); +#47=IFCBUILDING('3e580MQFTCD9tCSaZWRPi9',#46,'My Building',$,$,#73,$,$,.ELEMENT.,$,$,$); +#53=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605); +#54=IFCBUILDINGSTOREY('3XFkAr6KbAsP5wR3gxi3my',#53,'My Storey',$,$,#80,$,$,.ELEMENT.,$); +#60=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605); +#61=IFCRELAGGREGATES('2OWfFyDQn0qP0Vd6NWGX7k',#60,$,$,#9,(#40)); +#62=IFCCARTESIANPOINT((0.,0.,0.)); +#63=IFCDIRECTION((0.,0.,1.)); +#64=IFCDIRECTION((1.,0.,0.)); +#65=IFCAXIS2PLACEMENT3D(#62,#63,#64); +#66=IFCLOCALPLACEMENT($,#65); +#67=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605); +#68=IFCRELAGGREGATES('3_X_vfPpXDaO3NODBJgmSp',#67,$,$,#40,(#47)); +#69=IFCCARTESIANPOINT((0.,0.,0.)); +#70=IFCDIRECTION((0.,0.,1.)); +#71=IFCDIRECTION((1.,0.,0.)); +#72=IFCAXIS2PLACEMENT3D(#69,#70,#71); +#73=IFCLOCALPLACEMENT(#66,#72); +#74=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605); +#75=IFCRELAGGREGATES('3ScF98CZD3pAa0SW$mhBHF',#74,$,$,#47,(#54)); +#76=IFCCARTESIANPOINT((0.,0.,0.)); +#77=IFCDIRECTION((0.,0.,1.)); +#78=IFCDIRECTION((1.,0.,0.)); +#79=IFCAXIS2PLACEMENT3D(#76,#77,#78); +#80=IFCLOCALPLACEMENT(#73,#79); +#110=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520632); +#111=IFCWALL('1lfiJzSCH1a8vjDuSLL4Ii',#110,'Cube',$,$,#203,$,$); +#112=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520818,#3,#7,1765520632); +#113=IFCRELCONTAINEDINSPATIALSTRUCTURE('2Gqx6vP7jB4x_h65Tawn0f',#112,$,$,(#111,#182,#150),#54); +#149=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520810); +#150=IFCWINDOW('1eE0btB_54tBL59wLXKO1B',#149,'Cube',$,$,#208,$,$,$,$); +#181=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520818); +#182=IFCBUILDINGELEMENTPART('0fmaoBJgz0kPBavO$EJkPn',#181,'Cube',$,$,#198,$,$); +#194=IFCCARTESIANPOINT((-3.82147288322449,-0.987768530845642,1.78445267677307)); +#195=IFCDIRECTION((0.,0.,1.)); +#196=IFCDIRECTION((1.,0.,0.)); +#197=IFCAXIS2PLACEMENT3D(#194,#195,#196); +#198=IFCLOCALPLACEMENT(#80,#197); +#199=IFCCARTESIANPOINT((0.,0.,0.)); +#200=IFCDIRECTION((0.,0.,1.)); +#201=IFCDIRECTION((1.,0.,0.)); +#202=IFCAXIS2PLACEMENT3D(#199,#200,#201); +#203=IFCLOCALPLACEMENT(#80,#202); +#204=IFCCARTESIANPOINT((0.,4.25822639465332,0.)); +#205=IFCDIRECTION((0.,0.,1.)); +#206=IFCDIRECTION((1.,0.,0.)); +#207=IFCAXIS2PLACEMENT3D(#204,#205,#206); +#208=IFCLOCALPLACEMENT(#80,#207); +ENDSEC; +END-ISO-10303-21; diff --git a/src/examples/README.md b/src/examples/README.md new file mode 100644 index 0000000000..fe309ed653 --- /dev/null +++ b/src/examples/README.md @@ -0,0 +1,22 @@ + +Example of building IfcParseExamples outside of the IfcOpenShell build tree. + +```powershell +$IFCOPENSHELL_ROOT="L:\Projects\Github\IfcOpenShell" +$PREFIX_PATH="$IFCOPENSHELL_ROOT\_deps\boost_1_86_0\stage\vs2022-x64" +$PREFIX_PATH+=";$IFCOPENSHELL_ROOT\_installed-vs2022-x64" +$PREFIX_PATH+=";$IFCOPENSHELL_ROOT\_deps-vs2022-x64-installed\rocksdb" +$PREFIX_PATH+=";$IFCOPENSHELL_ROOT\_deps-vs2022-x64-installed\zstd" +$PREFIX_PATH+=";L:\Software\usr\libxml2" + +cmake .. -G Ninja -DCMAKE_PREFIX_PATH="$PREFIX_PATH" -DCMAKE_BUILD_TYPE=Release +ninja -v +./IfcParseExamples.exe "../IfcParseExamples_test.ifc" +# Scanning file... +# Done scanning file +# Done resolving references +# Found 3 elements in ..\IfcParseExamples_test.ifc: +# #182=IfcBuildingElementPart('0fmaoBJgz0kPBavO$EJkPn',#181,'Cube',$,$,#193,#183,$) +# #111=IfcWall('1lfiJzSCH1a8vjDuSLL4Ii',#110,'Cube',$,$,#119,#114,$) +# #150=IfcWindow('1eE0btB_54tBL59wLXKO1B',#149,'Cube',$,$,#188,#151,$,$,$) +```