1+
2+ import os
3+
4+ from conan import ConanFile
5+ from conan .errors import ConanInvalidConfiguration
6+ from conan .tools .build import check_min_cppstd
7+ from conan .tools .cmake import CMake , CMakeDeps , CMakeToolchain , cmake_layout
8+ from conan .tools .files import copy , get , apply_conandata_patches , export_conandata_patches , rm , rmdir
9+
10+ required_conan_version = ">=2.1"
11+
12+ IFC_SCHEMAS = sorted (["2x3" , "4" , "4x1" , "4x2" , "4x3" , "4x3_tc1" , "4x3_add1" , "4x3_add2" ])
13+
14+ class IfcopenshellConan (ConanFile ):
15+ name = "ifcopenshell"
16+ description = "Open source IFC library and geometry engine"
17+ license = "LGPL-3.0"
18+ url = "https://github.com/conan-io/conan-center-index"
19+ homepage = "https://github.com/IfcOpenShell/IfcOpenShell"
20+ topics = ("ifc" , "bim" , "building" , "3d" )
21+ package_type = "library"
22+ settings = "os" , "arch" , "compiler" , "build_type"
23+ options = {
24+ "shared" : [True , False ],
25+ "fPIC" : [True , False ],
26+ "build_ifcgeom" : [True , False ],
27+ "build_ifcgeomserver" : [True , False ],
28+ "build_convert" : [True , False ],
29+ "build_convert_with_usd" : [True , False ],
30+ "build_convert_with_proj" : [True , False ],
31+ "ifcxml_support" : [True , False ],
32+ "use_mmap" : [True , False ],
33+ "with_cgal" : [True , False ],
34+ "with_hdf5" : [True , False ],
35+
36+ "with_ifcpython" : [True , False ],
37+ "with_examples" : [True , False ],
38+ "with_collada_support" : [True , False ],
39+ "build_qtviewer" : [True , False ],
40+ }
41+
42+ options .update ({f"schema_{ schema } " : [True , False ] for schema in IFC_SCHEMAS })
43+
44+ default_options = {
45+ "shared" : False ,
46+ "fPIC" : True ,
47+ "build_ifcgeom" : True ,
48+ "build_ifcgeomserver" : True ,
49+ "build_convert" : True ,
50+ "build_convert_with_usd" : False ,
51+ "build_convert_with_proj" : True ,
52+ "ifcxml_support" : True ,
53+ "use_mmap" : True ,
54+ "with_cgal" : True ,
55+ "with_hdf5" : True ,
56+
57+ "with_ifcpython" : True ,
58+ "with_examples" : True ,
59+ "with_collada_support" : False ,
60+ "build_qtviewer" : False ,
61+ }
62+ # Limit the default set of schemas to the basic ones and the latest to limit the size of the build.
63+ default_options .update ({f"schema_{ schema } " : schema in ["2x3" , "4" , "4x3_add2" ] for schema in IFC_SCHEMAS })
64+ implements = ["auto_shared_fpic" ]
65+
66+ @property
67+ def _selected_ifc_schemas (self ):
68+ return [schema for schema in IFC_SCHEMAS if self .options .get_safe (f"schema_{ schema } " )]
69+
70+ def export_sources (self ):
71+ export_conandata_patches (self )
72+
73+ def configure (self ):
74+ if self .options .shared :
75+ self .options .rm_safe ("fPIC" )
76+ if not self .options .build_ifcgeom :
77+ del self .options .with_cgal
78+
79+ def layout (self ):
80+ cmake_layout (self , src_folder = "src" )
81+
82+ def validate (self ):
83+ check_min_cppstd (self , 17 )
84+ if self .options .build_convert and not self .options .build_ifcgeom :
85+ raise ConanInvalidConfiguration ("build_convert requires build_ifcgeom to be enabled" )
86+
87+ def requirements (self ):
88+ # Boost release fixed by cgal to avoid conflict
89+ self .requires ("boost/1.83.0" , transitive_headers = True , transitive_libs = True )
90+ if self .options .get_safe ("with_hdf5" ):
91+ # Used in public serializers/HdfSerializer.h, ifcgeom/kernels/opencascade/IfcGeomTree.h
92+ self .requires ("hdf5/[^1.8]" , transitive_headers = True , transitive_libs = True )
93+ if self .options .build_ifcgeom :
94+ self .requires ("opencascade/[^7.8]" , transitive_headers = True , transitive_libs = True )
95+ # ifcgeom/taxonomy.h
96+ self .requires ("eigen/3.4.0" , transitive_headers = True )
97+ if self .options .get_safe ("with_cgal" ):
98+ # Used in ifcgeom/kernels/cgal public headers
99+ self .requires ("cgal/5.6.3" , transitive_headers = True , transitive_libs = True )
100+ # TODO migrate cpp to be compatible with latest cgal to avoid compilation errors on src/src/ifcconvert/validate_space_boundaries.cpp:
101+ # https://c3i.jfrog.io/artifactory/cci-build-logs/cci/prod/PR-27623/84/package_build_logs/build_log_ifcopenshell_0_8_3_cci_20250613_f8f37b5967ba18eef190cb0e92b6b561_9f5b6011d7ba49ff30af97cb4929b54a80903d97.txt
102+ # self.requires("cgal/[>=5.6]", transitive_headers=True, transitive_libs=True)
103+ if self .options .get_safe ("with_cgal" ) or self .options .ifcxml_support :
104+ self .requires ("libxml2/[^2.12.5]" )
105+ if self .options .build_convert :
106+ if self .options .build_convert_with_usd :
107+ # See https://github.com/conan-io/conan-center-index/pull/24506
108+ self .requires ("openusd/[^25.02]" )
109+ if self .options .build_convert_with_proj :
110+ self .requires ("proj/[^9.6.0]" )
111+ if self .options .with_collada_support :
112+ self .requires ("opencollada/[^1.6.68]" )
113+ if self .options .build_qtviewer :
114+ self .requires ("qt/6.8.3" )
115+ self .requires ("openscenegraph/3.6.5" )
116+
117+ def build_requirements (self ):
118+ self .tool_requires ("cmake/[>=3.21 <5]" )
119+
120+ def source (self ):
121+ get (self , ** self .conan_data ["sources" ][self .version ], strip_root = True )
122+
123+ def generate (self ):
124+ tc = CMakeToolchain (self )
125+ tc .cache_variables ["SCHEMA_VERSIONS" ] = ";" .join (self ._selected_ifc_schemas )
126+
127+ tc .cache_variables ["BUILD_IFCGEOM" ] = self .options .build_ifcgeom
128+ tc .cache_variables ["BUILD_GEOMSERVER" ] = self .options .build_ifcgeomserver
129+ tc .cache_variables ["BUILD_CONVERT" ] = self .options .build_convert
130+ # validate_space_boundaries.cpp:106:57: error: no matching function for call to 'IfcEntityInstanceData::toString() const
131+ # See https://c3i.jfrog.io/artifactory/cci-build-logs/cci/prod/PR-27623/86/package_build_logs/build_log_ifcopenshell_0_8_3_cci_20250613_855f5322a78c6ae836318b516e5c29ba_b8f0ca9f77a4d376fb7cb9ba9f229be5f13244f9.txt
132+ # tc.cache_variables["WITH_RELATIONSHIP_VALIDATION"] = self.options.build_convert
133+ tc .cache_variables ["USD_SUPPORT" ] = self .options .build_convert and self .options .build_convert_with_usd
134+ tc .cache_variables ["WITH_PROJ" ] = self .options .build_convert and self .options .build_convert_with_proj
135+ tc .cache_variables ["IFCXML_SUPPORT" ] = self .options .ifcxml_support
136+ tc .cache_variables ["USE_MMAP" ] = self .options .use_mmap
137+ tc .cache_variables ["WITH_OPENCASCADE" ] = self .options .build_ifcgeom
138+ tc .cache_variables ["WITH_CGAL" ] = self .options .get_safe ("with_cgal" , False )
139+ tc .cache_variables ["HDF5_SUPPORT" ] = self .options .get_safe ("with_hdf5" , False )
140+ tc .cache_variables ["COLLADA_SUPPORT" ] = self .options .with_collada_support
141+
142+ tc .cache_variables ["BUILD_QTVIEWER" ] = self .options .build_qtviewer
143+
144+ tc .cache_variables ["BUILD_IFCPYTHON" ] = False
145+ tc .cache_variables ["BUILD_EXAMPLES" ] = True
146+
147+ tc .generate ()
148+
149+ deps = CMakeDeps (self )
150+ deps .generate ()
151+
152+ def build (self ):
153+ apply_conandata_patches (self )
154+ rm (self , "*.cmake" , os .path .join (self .source_folder , "cmake" ))
155+ cmake = CMake (self )
156+ cmake .configure (build_script_folder = "cmake" )
157+ # cmake.build()
158+ cmake .build (cli_args = ["--verbose" ], build_tool_args = ["-j" , "2" ])
159+
160+ def package (self ):
161+ copy (self , "COPYING*" , self .source_folder , os .path .join (self .package_folder , "licenses" ))
162+ cmake = CMake (self )
163+ cmake .install ()
164+ rmdir (self , os .path .join (self .package_folder , "lib" , "cmake" ))
165+
166+
167+ def package_info (self ):
168+ # No official CMake or .pc config exported. Based on CPack values for consistency.
169+ self .cpp_info .set_property ("cmake_file_name" , "IfcOpenShell" )
170+
171+ def _add_component (name , requires = None ):
172+ component = self .cpp_info .components [name ]
173+ component .set_property ("cmake_target_name" , name )
174+ component .libs = [name ]
175+ component .requires = requires or []
176+ return component
177+
178+ ifcparse = _add_component ("IfcParse" , requires = [
179+ "boost::system" ,
180+ "boost::program_options" ,
181+ "boost::regex" ,
182+ "boost::thread" ,
183+ "boost::date_time" ,
184+ ])
185+ if self .options .use_mmap :
186+ ifcparse .requires .extend (["boost::iostreams" , "boost::filesystem" ,])
187+ ifcparse .defines .append ("USE_MMAP" )
188+ if self .options .ifcxml_support :
189+ ifcparse .requires .append ("libxml2::libxml2" )
190+ ifcparse .defines .append ("WITH_IFCXML" )
191+ ifcparse .defines .append (f"SCHEMA_SEQ=({ ')(' .join (self ._selected_ifc_schemas )} )" )
192+ for schema in self ._selected_ifc_schemas :
193+ ifcparse .defines .append (f"HAS_SCHEMA_{ schema } " )
194+ if self .options .shared :
195+ ifcparse .defines .append ("IFC_SHARED_BUILD" )
196+ if self .settings .os in ["Linux" , "FreeBSD" ]:
197+ ifcparse .system_libs = ["m" , "dl" ]
198+
199+ if self .options .build_ifcgeom :
200+ ifcgeom = _add_component ("IfcGeom" , requires = ["IfcParse" , "eigen::eigen" ])
201+ if self .settings .os in ["Linux" , "FreeBSD" ]:
202+ ifcgeom .system_libs .append ("pthread" )
203+ # When kernels, mappings and geometry_serializers are built as OBJECT target, we define conan dependencies directly to IfcGeom
204+ if self .options .get_safe ("with_cgal" ):
205+ # ifcgeom.requires.append("geometry_kernel_cgal")
206+ ifcgeom .defines .append ("IFOPSH_WITH_CGAL" )
207+ ifcgeom .requires += ["cgal::cgal" , "eigen::eigen" ]
208+ ifcgeom .requires += [
209+ "opencascade::occt_tkernel" ,
210+ "opencascade::occt_tkmath" ,
211+ "opencascade::occt_tkbrep" ,
212+ "opencascade::occt_tkgeombase" ,
213+ "opencascade::occt_tkgeomalgo" ,
214+ "opencascade::occt_tkg3d" ,
215+ "opencascade::occt_tkg2d" ,
216+ "opencascade::occt_tkshhealing" ,
217+ "opencascade::occt_tktopalgo" ,
218+ "opencascade::occt_tkmesh" ,
219+ "opencascade::occt_tkprim" ,
220+ "opencascade::occt_tkbool" ,
221+ "opencascade::occt_tkbo" ,
222+ "opencascade::occt_tkfillet" ,
223+ "opencascade::occt_tkxsbase" ,
224+ "opencascade::occt_tkoffset" ,
225+ "opencascade::occt_tkhlr" ,
226+ "eigen::eigen" ,
227+ ]
228+ ifcgeom .defines .append ("IFOPSH_WITH_OPENCASCADE" )
229+ if self .options .with_hdf5 :
230+ ifcgeom .requires .append ("hdf5::hdf5_cpp" )
231+
232+ if self .options .build_convert :
233+ serializers = _add_component ("Serializers" , requires = ["IfcGeom" ])
234+ if self .options .with_hdf5 :
235+ serializers .requires .append ("hdf5::hdf5_cpp" )
236+ if self .options .build_convert_with_usd :
237+ serializers .requires .append ("openusd::openusd" )
238+ if self .options .build_convert_with_proj :
239+ serializers .requires .append ("proj::proj" )
240+ if self .options .with_collada_support :
241+ serializers .requires .append ("opencollada::opencollada" )
0 commit comments