@@ -89,6 +89,11 @@ class InstallOptions:
89
89
llvm_repo : str = "https://github.com/llvm/llvm-project.git"
90
90
llvm_commit : str = "dd7a3d4d798e30dfe53b5bbbbcd9a23c24ea1af9"
91
91
92
+ # Information to create run configurations
93
+ generate_run_configs : bool = field (default_factory = lambda : running_from_mrdocs_source_dir ())
94
+ jetbrains_run_config_dir : str = "<mrdocs-src-dir>/.run"
95
+ boost_src_dir : str = "<mrdocs-src-dir>/../boost"
96
+
92
97
# Meta
93
98
non_interactive : bool = False
94
99
@@ -125,6 +130,9 @@ class InstallOptions:
125
130
"llvm_install_dir" : "Directory where LLVM will be installed." ,
126
131
"llvm_repo" : "URL of the LLVM project repository to clone." ,
127
132
"llvm_commit" : "Specific commit hash of LLVM to checkout." ,
133
+ "generate_run_configs" : "Whether to generate run configurations for IDEs." ,
134
+ "jetbrains_run_config_dir" : "Directory where JetBrains run configurations will be stored." ,
135
+ "boost_src_dir" : "Directory where the source files of the Boost libraries are located." ,
128
136
"non_interactive" : "Whether to use all default options without interactive prompts."
129
137
}
130
138
@@ -797,16 +805,161 @@ def install_mrdocs(self):
797
805
else :
798
806
print (f"\n MrDocs has been successfully installed in { self .options .mrdocs_install_dir } .\n " )
799
807
808
+
809
+ def generate_clion_run_configs (self , configs ):
810
+ import xml .etree .ElementTree as ET
811
+
812
+ # Generate CLion run configurations for MrDocs
813
+ # For each configuration, we create an XML file in <mrdocs-src-dir>/.run
814
+ # named <config-name>.run.xml
815
+ run_dir = os .path .join (self .options .mrdocs_src_dir , ".run" )
816
+ os .makedirs (run_dir , exist_ok = True )
817
+ for config in configs :
818
+ config_name = config ["name" ]
819
+ run_config_path = os .path .join (run_dir , f"{ config_name } .run.xml" )
820
+ root = ET .Element ("component" , name = "ProjectRunConfigurationManager" )
821
+ config = ET .SubElement (root , "configuration" , {
822
+ "default" : "false" ,
823
+ "name" : config ["name" ],
824
+ "type" : "CMakeRunConfiguration" ,
825
+ "factoryName" : "Application" ,
826
+ "PROGRAM_PARAMS" : " " .join (config ["args" ]),
827
+ "REDIRECT_INPUT" : "false" ,
828
+ "ELEVATE" : "false" ,
829
+ "USE_EXTERNAL_CONSOLE" : "false" ,
830
+ "EMULATE_TERMINAL" : "false" ,
831
+ "PASS_PARENT_ENVS_2" : "true" ,
832
+ "PROJECT_NAME" : "MrDocs" ,
833
+ "TARGET_NAME" : config ["target" ],
834
+ "CONFIG_NAME" : self .options .mrdocs_preset_name or "debug" ,
835
+ "RUN_TARGET_PROJECT_NAME" : "MrDocs" ,
836
+ "RUN_TARGET_NAME" : config ["target" ]
837
+ })
838
+ method = ET .SubElement (config , "method" , v = "2" )
839
+ ET .SubElement (method , "option" , name = "com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" , enabled = "true" )
840
+ tree = ET .ElementTree (root )
841
+ tree .write (run_config_path , encoding = "utf-8" , xml_declaration = False )
842
+
843
+ def generate_visual_studio_run_configs (self , configs ):
844
+ # Visual Studio launch configs are stored in .vs/launch.vs.json
845
+ vs_dir = os .path .join (self .options .mrdocs_src_dir , ".vs" )
846
+ os .makedirs (vs_dir , exist_ok = True )
847
+ launch_path = os .path .join (vs_dir , "launch.vs.json" )
848
+
849
+ # Load existing configs if present
850
+ if os .path .exists (launch_path ):
851
+ with open (launch_path , "r" ) as f :
852
+ launch_data = json .load (f )
853
+ else :
854
+ launch_data = {"version" : "0.2.1" , "configurations" : []}
855
+
856
+ # Build a dict for quick lookup by name
857
+ configs_by_name = {cfg .get ("name" ): cfg for cfg in launch_data .get ("configurations" , [])}
858
+
859
+ for config in configs :
860
+ new_cfg = {
861
+ "name" : config ["name" ],
862
+ "type" : "default" ,
863
+ "project" : "MrDocs" ,
864
+ "projectTarget" : config ["target" ],
865
+ "args" : config ["args" ],
866
+ "cwd" : self .options .mrdocs_build_dir ,
867
+ "env" : {},
868
+ "stopAtEntry" : False
869
+ }
870
+ # Replace or add
871
+ configs_by_name [config ["name" ]] = new_cfg
872
+
873
+ # Write back all configs
874
+ launch_data ["configurations" ] = list (configs_by_name .values ())
875
+ with open (launch_path , "w" ) as f :
876
+ json .dump (launch_data , f , indent = 4 )
877
+
878
+ def generate_run_configs (self ):
879
+ # Configurations using MrDocs executable
880
+ configs = [{
881
+ "name" : "MrDocs Version" ,
882
+ "target" : "mrdocs" ,
883
+ "args" : ["--version" ]
884
+ }, {
885
+ "name" : "MrDocs Help" ,
886
+ "target" : "mrdocs" ,
887
+ "args" : ["--help" ]
888
+ }]
889
+
890
+ # Configuration to run unit tests
891
+ if self .options .mrdocs_build_tests :
892
+ configs .append ({
893
+ "name" : "MrDocs Unit Tests" ,
894
+ "target" : "mrdocs-test" ,
895
+ "args" : [
896
+ '--unit=true'
897
+ ]
898
+ })
899
+
900
+ # Configurations to Update/Test/Create test fixtures
901
+ for verb in ["update" , "test" , "create" ]:
902
+ for generator in ["adoc" , "html" , "xml" ]:
903
+ configs .append ({
904
+ "name" : f"MrDocs { verb .title ()} Test Fixtures ({ generator .upper ()} )" ,
905
+ "target" : "mrdocs-test" ,
906
+ "args" : [
907
+ f'"{ self .options .mrdocs_src_dir } /test-files/golden-tests"' ,
908
+ '--unit=false' ,
909
+ f'--action={ verb } ' ,
910
+ f'--generator={ generator } ' ,
911
+ f'--addons="{ self .options .mrdocs_src_dir } /share/mrdocs/addons"' ,
912
+ f'--stdlib-includes="{ self .options .llvm_install_dir } /include/c++/v1"' ,
913
+ f'--stdlib-includes="{ self .options .llvm_install_dir } /lib/clang/20/include"' ,
914
+ f'--libc-includes="{ self .options .mrdocs_src_dir } /share/mrdocs/headers/libc-stubs"' ,
915
+ '--log-level=warn'
916
+ ]
917
+ })
918
+
919
+ self .prompt_option ("boost_src_dir" )
920
+ if self .options .boost_src_dir and os .path .exists (self .options .boost_src_dir ):
921
+ boost_libs = os .path .join (self .options .boost_src_dir , 'libs' )
922
+ if os .path .exists (boost_libs ):
923
+ for lib in os .listdir (boost_libs ):
924
+ mrdocs_config = os .path .join (boost_libs , lib , 'doc' , 'mrdocs.yml' )
925
+ if os .path .exists (mrdocs_config ):
926
+ print (f"Generating run configuration for Boost library '{ lib } '" )
927
+ configs .append ({
928
+ "name" : f"Boost.{ lib .title ()} Documentation" ,
929
+ "target" : "mrdocs" ,
930
+ "args" : [
931
+ '"../CMakeLists.txt"' ,
932
+ f'--config="{ self .options .boost_src_dir } /libs/{ lib } /doc/mrdocs.yml"' ,
933
+ f'--output="{ self .options .boost_src_dir } /libs/{ lib } /doc/modules/reference/pages"' ,
934
+ f'--generator=adoc' ,
935
+ f'--addons="{ self .options .mrdocs_src_dir } /share/mrdocs/addons"' ,
936
+ f'--stdlib-includes="{ self .options .llvm_install_dir } /include/c++/v1"' ,
937
+ f'--stdlib-includes="{ self .options .llvm_install_dir } /lib/clang/20/include"' ,
938
+ f'--libc-includes="{ self .options .mrdocs_src_dir } /share/mrdocs/headers/libc-stubs"' ,
939
+ f'--tagfile=reference.tag.xml' ,
940
+ '--multipage=true' ,
941
+ '--concurrency=32' ,
942
+ '--log-level=debug'
943
+ ]
944
+ })
945
+ else :
946
+ print (f"Warning: Boost source directory '{ self .options .boost_src_dir } ' does not contain 'libs' directory. Skipping Boost documentation target generation." )
947
+
948
+ self .generate_clion_run_configs (configs )
949
+ self .generate_visual_studio_run_configs (configs )
950
+
800
951
def install_all (self ):
801
952
self .check_tools ()
802
953
self .setup_mrdocs_dir ()
803
954
self .setup_third_party_dir ()
804
955
self .install_duktape ()
805
- if self .options . mrdocs_build_tests :
956
+ if self .prompt_option ( " mrdocs_build_tests" ) :
806
957
self .install_libxml2 ()
807
958
self .install_llvm ()
808
959
self .create_cmake_presets ()
809
960
self .install_mrdocs ()
961
+ if self .prompt_option ("generate_run_configs" ):
962
+ self .generate_run_configs ()
810
963
811
964
def get_command_line_args ():
812
965
"""
0 commit comments