58
58
BOOL2XCODEBOOL = {True : 'YES' , False : 'NO' }
59
59
LINKABLE_EXTENSIONS = {'.o' , '.a' , '.obj' , '.so' , '.dylib' }
60
60
61
+ class FileTreeEntry :
62
+
63
+ def __init__ (self ):
64
+ self .subdirs = {}
65
+ self .targets = []
66
+
61
67
class PbxItem :
62
68
def __init__ (self , value , comment = '' ):
63
69
self .value = value
@@ -267,6 +273,7 @@ def generate(self):
267
273
self .generate_pbxdep_map ()
268
274
self .generate_containerproxy_map ()
269
275
self .generate_target_file_maps ()
276
+ self .generate_build_file_maps ()
270
277
self .proj_dir = os .path .join (self .environment .get_build_dir (), self .build .project_name + '.xcodeproj' )
271
278
os .makedirs (self .proj_dir , exist_ok = True )
272
279
self .proj_file = os .path .join (self .proj_dir , 'project.pbxproj' )
@@ -321,7 +328,6 @@ def get_xcodetype(self, fname):
321
328
xcodetype = XCODETYPEMAP .get (fname .split ('.' )[- 1 ].lower ())
322
329
if not xcodetype :
323
330
xcodetype = 'sourcecode.unknown'
324
- mlog .warning (f'Unknown file type "{ fname } " fallbacking to "{ xcodetype } ". Xcode project might be malformed.' )
325
331
return xcodetype
326
332
327
333
def generate_filemap (self ):
@@ -509,6 +515,12 @@ def generate_target_file_maps_impl(self, targets):
509
515
else :
510
516
raise RuntimeError ('Unknown input type ' + str (o ))
511
517
518
+ def generate_build_file_maps (self ):
519
+ for buildfile in self .interpreter .get_build_def_files ():
520
+ assert (isinstance (buildfile , str ))
521
+ self .buildfile_ids [buildfile ] = self .gen_id ()
522
+ self .fileref_ids [buildfile ] = self .gen_id ()
523
+
512
524
def generate_source_phase_map (self ):
513
525
self .source_phase = {}
514
526
for t in self .build_targets :
@@ -825,6 +837,18 @@ def generate_pbx_file_reference(self, objects_dict):
825
837
custom_dict .add_item ('sourceTree' , 'SOURCE_ROOT' )
826
838
objects_dict .add_item (self .custom_target_output_fileref [o ], custom_dict )
827
839
840
+ for buildfile in self .interpreter .get_build_def_files ():
841
+ basename = os .path .split (buildfile )[1 ]
842
+ buildfile_dict = PbxDict ()
843
+ typestr = self .get_xcodetype (buildfile )
844
+ buildfile_dict .add_item ('isa' , 'PBXFileReference' )
845
+ buildfile_dict .add_item ('explicitFileType' , '"' + typestr + '"' )
846
+ buildfile_dict .add_item ('name' , f'"{ basename } "' )
847
+ buildfile_dict .add_item ('path' , f'"{ buildfile } "' )
848
+ buildfile_dict .add_item ('refType' , 0 )
849
+ buildfile_dict .add_item ('sourceTree' , 'SOURCE_ROOT' )
850
+ objects_dict .add_item (self .fileref_ids [buildfile ], buildfile_dict )
851
+
828
852
def generate_pbx_frameworks_buildphase (self , objects_dict ):
829
853
for t in self .build_targets .values ():
830
854
bt_dict = PbxDict ()
@@ -848,33 +872,22 @@ def generate_pbx_group(self, objects_dict):
848
872
for t in self .custom_targets :
849
873
groupmap [t ] = self .gen_id ()
850
874
target_src_map [t ] = self .gen_id ()
851
- sources_id = self .gen_id ()
875
+ projecttree_id = self .gen_id ()
852
876
resources_id = self .gen_id ()
853
877
products_id = self .gen_id ()
854
- frameworks_id = self .gen_id ()
878
+ frameworks_id = self .gen_id ()
855
879
main_dict = PbxDict ()
856
880
objects_dict .add_item (self .maingroup_id , main_dict )
857
881
main_dict .add_item ('isa' , 'PBXGroup' )
858
882
main_children = PbxArray ()
859
883
main_dict .add_item ('children' , main_children )
860
- main_children .add_item (sources_id , 'Sources ' )
884
+ main_children .add_item (projecttree_id , 'Project tree ' )
861
885
main_children .add_item (resources_id , 'Resources' )
862
886
main_children .add_item (products_id , 'Products' )
863
887
main_children .add_item (frameworks_id , 'Frameworks' )
864
888
main_dict .add_item ('sourceTree' , '"<group>"' )
865
889
866
- # Sources
867
- source_dict = PbxDict ()
868
- objects_dict .add_item (sources_id , source_dict , 'Sources' )
869
- source_dict .add_item ('isa' , 'PBXGroup' )
870
- source_children = PbxArray ()
871
- source_dict .add_item ('children' , source_children )
872
- for t in self .build_targets :
873
- source_children .add_item (groupmap [t ], t )
874
- for t in self .custom_targets :
875
- source_children .add_item (groupmap [t ], t )
876
- source_dict .add_item ('name' , 'Sources' )
877
- source_dict .add_item ('sourceTree' , '"<group>"' )
890
+ self .add_projecttree (objects_dict , projecttree_id )
878
891
879
892
resource_dict = PbxDict ()
880
893
objects_dict .add_item (resources_id , resource_dict , 'Resources' )
@@ -900,44 +913,6 @@ def generate_pbx_group(self, objects_dict):
900
913
frameworks_dict .add_item ('name' , 'Frameworks' )
901
914
frameworks_dict .add_item ('sourceTree' , '"<group>"' )
902
915
903
- # Targets
904
- for tname , t in self .build_targets .items ():
905
- target_dict = PbxDict ()
906
- objects_dict .add_item (groupmap [tname ], target_dict , tname )
907
- target_dict .add_item ('isa' , 'PBXGroup' )
908
- target_children = PbxArray ()
909
- target_dict .add_item ('children' , target_children )
910
- target_children .add_item (target_src_map [tname ], 'Source files' )
911
- if t .subproject :
912
- target_dict .add_item ('name' , f'"{ t .subproject } • { t } "' )
913
- else :
914
- target_dict .add_item ('name' , f'"{ t } "' )
915
- target_dict .add_item ('sourceTree' , '"<group>"' )
916
- source_files_dict = PbxDict ()
917
- objects_dict .add_item (target_src_map [tname ], source_files_dict , 'Source files' )
918
- source_files_dict .add_item ('isa' , 'PBXGroup' )
919
- source_file_children = PbxArray ()
920
- source_files_dict .add_item ('children' , source_file_children )
921
- for s in t .sources :
922
- if isinstance (s , mesonlib .File ):
923
- s = os .path .join (s .subdir , s .fname )
924
- elif isinstance (s , str ):
925
- s = os .path .joni (t .subdir , s )
926
- else :
927
- continue
928
- source_file_children .add_item (self .fileref_ids [(tname , s )], s )
929
- for o in t .objects :
930
- if isinstance (o , build .ExtractedObjects ):
931
- # Do not show built object files in the project tree.
932
- continue
933
- if isinstance (o , mesonlib .File ):
934
- o = os .path .join (o .subdir , o .fname )
935
- else :
936
- o = os .path .join (t .subdir , o )
937
- source_file_children .add_item (self .fileref_ids [(tname , o )], o )
938
- source_files_dict .add_item ('name' , '"Source files"' )
939
- source_files_dict .add_item ('sourceTree' , '"<group>"' )
940
-
941
916
for tname , t in self .custom_targets .items ():
942
917
target_dict = PbxDict ()
943
918
objects_dict .add_item (groupmap [tname ], target_dict , tname )
@@ -977,6 +952,89 @@ def generate_pbx_group(self, objects_dict):
977
952
product_dict .add_item ('name' , 'Products' )
978
953
product_dict .add_item ('sourceTree' , '"<group>"' )
979
954
955
+ def write_group_target_entry (self , objects_dict , t ):
956
+ tid = t .get_id ()
957
+ group_id = self .gen_id ()
958
+ target_dict = PbxDict ()
959
+ objects_dict .add_item (group_id , target_dict , tid )
960
+ target_dict .add_item ('isa' , 'PBXGroup' )
961
+ target_children = PbxArray ()
962
+ target_dict .add_item ('children' , target_children )
963
+ target_dict .add_item ('name' , f'"{ t } · target"' )
964
+ target_dict .add_item ('sourceTree' , '"<group>"' )
965
+ source_files_dict = PbxDict ()
966
+ for s in t .sources :
967
+ if isinstance (s , mesonlib .File ):
968
+ s = os .path .join (s .subdir , s .fname )
969
+ elif isinstance (s , str ):
970
+ s = os .path .joni (t .subdir , s )
971
+ else :
972
+ continue
973
+ target_children .add_item (self .fileref_ids [(tid , s )], s )
974
+ for o in t .objects :
975
+ if isinstance (o , build .ExtractedObjects ):
976
+ # Do not show built object files in the project tree.
977
+ continue
978
+ if isinstance (o , mesonlib .File ):
979
+ o = os .path .join (o .subdir , o .fname )
980
+ else :
981
+ o = os .path .join (t .subdir , o )
982
+ target_children .add_item (self .fileref_ids [(tid , o )], o )
983
+ source_files_dict .add_item ('name' , '"Source files"' )
984
+ source_files_dict .add_item ('sourceTree' , '"<group>"' )
985
+ return group_id
986
+
987
+ def add_projecttree (self , objects_dict , projecttree_id ):
988
+ root_dict = PbxDict ()
989
+ objects_dict .add_item (projecttree_id , root_dict , "Root of project tree" )
990
+ root_dict .add_item ('isa' , 'PBXGroup' )
991
+ target_children = PbxArray ()
992
+ root_dict .add_item ('children' , target_children )
993
+ root_dict .add_item ('name' , '"Project root"' )
994
+ root_dict .add_item ('sourceTree' , '"<group>"' )
995
+
996
+ project_tree = self .generate_project_tree ()
997
+ self .write_tree (objects_dict , project_tree , target_children , '' )
998
+
999
+ def write_tree (self , objects_dict , tree_node , children_array , current_subdir ):
1000
+ subdir_dict = PbxDict ()
1001
+ subdir_children = PbxArray ()
1002
+ for subdir_name , subdir_node in tree_node .subdirs .items ():
1003
+ subdir_id = self .gen_id ()
1004
+ objects_dict .add_item (subdir_id , subdir_dict )
1005
+ children_array .add_item (subdir_id )
1006
+ subdir_dict .add_item ('isa' , 'PBXGroup' )
1007
+ subdir_dict .add_item ('children' , subdir_children )
1008
+ subdir_dict .add_item ('name' , f'"{ subdir_name } "' )
1009
+ subdir_dict .add_item ('sourceTree' , '"<group>"' )
1010
+ self .write_tree (objects_dict , subdir_node , subdir_children , os .path .join (current_subdir , subdir_name ))
1011
+ for target in tree_node .targets :
1012
+ group_id = self .write_group_target_entry (objects_dict , target )
1013
+ children_array .add_item (group_id )
1014
+ potentials = [os .path .join (current_subdir , 'meson.build' ),
1015
+ os .path .join (current_subdir , 'meson_options.txt' )]
1016
+ for bf in potentials :
1017
+ i = self .fileref_ids .get (bf , None )
1018
+ if i :
1019
+ children_array .add_item (i )
1020
+
1021
+
1022
+ def generate_project_tree (self ):
1023
+ tree_info = FileTreeEntry ()
1024
+ for tname , t in self .build_targets .items ():
1025
+ self .add_target_to_tree (tree_info , t )
1026
+ return tree_info
1027
+
1028
+ def add_target_to_tree (self , tree_root , t ):
1029
+ current_node = tree_root
1030
+ path_segments = t .subdir .split ('/' )
1031
+ for s in path_segments :
1032
+ if not s :
1033
+ continue
1034
+ if s not in current_node .subdirs :
1035
+ current_node .subdirs [s ] = FileTreeEntry ()
1036
+ current_node = current_node .subdirs [s ]
1037
+ current_node .targets .append (t )
980
1038
981
1039
def generate_pbx_native_target (self , objects_dict ):
982
1040
for tname , idval in self .native_targets .items ():
0 commit comments