22using System . IO ;
33using System . Diagnostics ;
44using System ;
5+ using System . Linq ;
6+ using System . Collections . Generic ;
7+ using UnrealBuildBase ;
8+ using EpicGames . Core ;
59
610[ Serializable ]
711public class EcsactSdkNotFound : Exception {
@@ -33,8 +37,11 @@ public Ecsact(ReadOnlyTargetRules Target) : base(Target) {
3337 PrivateDependencyModuleNames . Add ( "UnrealEd" ) ;
3438 }
3539
36- var ecsactSdkIncludeDir = GetEcsactSdkIncludeDir ( ) ;
37- PublicIncludePaths . Add ( ecsactSdkIncludeDir ) ;
40+ var EcsactSdkVersion = GetEcsactSdkVersion ( ) ;
41+ Environment . SetEnvironmentVariable ( "EcsactPlugin_SdkVersion" , EcsactSdkVersion ) ;
42+
43+ var EcsactSdkIncludeDir = GetEcsactSdkIncludeDir ( ) ;
44+ PublicIncludePaths . Add ( EcsactSdkIncludeDir ) ;
3845
3946 // NOTE: For now these APIs are loaded on module startup
4047 PublicDefinitions . AddRange ( new string [ ] {
@@ -45,13 +52,64 @@ public Ecsact(ReadOnlyTargetRules Target) : base(Target) {
4552 "ECSACT_SERIALIZE_API_LOAD_AT_RUNTIME" ,
4653 "ECSACT_STATIC_API_LOAD_AT_RUNTIME" ,
4754 } ) ;
55+
56+ var EcsactSources = GetEcsactSources ( ) ;
57+
58+ if ( EcsactSources . Length > 0 ) {
59+ var CodegenArgs = new List < string > ( ) {
60+ "codegen" ,
61+ "--format=json" ,
62+ "--plugin=cpp_header" ,
63+ "--plugin=systems_header" ,
64+ "--plugin=cpp_systems_header" ,
65+ "--plugin=cpp_systems_source"
66+ } ;
67+ CodegenArgs . AddRange ( EcsactSources ) ;
68+ ExecEcsactCli ( CodegenArgs ) ;
69+ }
70+ }
71+
72+ private string [ ] GetEcsactSources ( ) {
73+ var projectRoot = GetProjectRoot ( Target ) ;
74+ return Directory . GetFiles (
75+ Path . Combine ( projectRoot . FullName , "Source" ) ,
76+ "*.ecsact" ,
77+ SearchOption . AllDirectories
78+ ) ;
79+ }
80+
81+ private string GetEcsactSdkVersion ( ) {
82+ var version = "" ;
83+
84+ try {
85+ var startInfo = new ProcessStartInfo ( ) ;
86+ startInfo . FileName = "ecsact" ;
87+ startInfo . Arguments = "--version" ;
88+ startInfo . RedirectStandardOutput = true ;
89+ startInfo . UseShellExecute = false ;
90+ startInfo . CreateNoWindow = true ;
91+
92+ using ( Process process = Process . Start ( startInfo ) ) {
93+ using ( StreamReader reader = process . StandardOutput ) {
94+ version = reader . ReadToEnd ( ) . Trim ( ) ;
95+ }
96+ }
97+ } catch ( Exception err ) {
98+ throw new EcsactSdkNotFound ( err ) ;
99+ }
100+
101+ if ( String . IsNullOrEmpty ( version ) ) {
102+ throw new EcsactSdkNotFound ( null ) ;
103+ }
104+
105+ return version ;
48106 }
49107
50108 private string GetEcsactSdkIncludeDir ( ) {
51109 var includePath = "" ;
52110
53111 try {
54- ProcessStartInfo startInfo = new ProcessStartInfo ( ) ;
112+ var startInfo = new ProcessStartInfo ( ) ;
55113 startInfo . FileName = "ecsact" ;
56114 startInfo . Arguments = "config include_dir" ;
57115 startInfo . RedirectStandardOutput = true ;
@@ -69,4 +127,47 @@ private string GetEcsactSdkIncludeDir() {
69127
70128 return includePath ;
71129 }
130+
131+ private void ExecEcsactCli ( IList < string > Args ) {
132+ try {
133+ var StartInfo = new ProcessStartInfo ( ) ;
134+ StartInfo . FileName = "ecsact" ;
135+ foreach ( var Arg in Args ) {
136+ StartInfo . ArgumentList . Add ( Arg ) ;
137+ }
138+ StartInfo . UseShellExecute = false ;
139+ StartInfo . CreateNoWindow = true ;
140+ StartInfo . RedirectStandardOutput = true ;
141+ StartInfo . RedirectStandardError = true ;
142+ var Proc = Process . Start ( StartInfo ) ;
143+
144+ var Line = "" ;
145+ while ( ( Line = Proc . StandardOutput . ReadLine ( ) ) != null ) {
146+ Console . WriteLine ( Line ) ;
147+ }
148+
149+ Proc . WaitForExit ( ) ;
150+ if ( Proc . ExitCode != 0 ) {
151+ throw new BuildException ( "ecsact exited with code: " + Proc . ExitCode ) ;
152+ }
153+ } catch ( BuildException err ) {
154+ throw err ;
155+ } catch ( Exception err ) {
156+ throw new EcsactSdkNotFound ( err ) ;
157+ }
158+ }
159+
160+ private DirectoryReference GetProjectRoot ( ReadOnlyTargetRules Target ) {
161+ if ( Target . ProjectFile != null ) {
162+ return Target . ProjectFile . Directory ;
163+ }
164+
165+ // Without a Target.ProjectFile we're probably installed as an Engine plugin.
166+ // Only information we have about the project is the current directory.
167+ var Root = new DirectoryReference ( Directory . GetCurrentDirectory ( ) ) ;
168+ while ( Root != null && ! File . Exists ( Path . Combine ( Root . FullName , "*.uproject" ) ) ) {
169+ Root = Root . ParentDirectory ;
170+ }
171+ return Root ;
172+ }
72173}
0 commit comments