Skip to content

Commit 2911a27

Browse files
committed
buildtool: functionalize, use incremental build
1 parent 39a77e8 commit 2911a27

File tree

1 file changed

+65
-84
lines changed

1 file changed

+65
-84
lines changed

buildfile.m

Lines changed: 65 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
plan("clean") = matlab.buildtool.tasks.CleanTask;
2424
end
2525

26-
plan("build_c") = matlab.buildtool.Task(Actions=@subprocess_build_c);
27-
plan("build_cpp") = matlab.buildtool.Task(Actions=@subprocess_build_cpp);
28-
plan("build_fortran") = matlab.buildtool.Task(Actions=@subprocess_build_fortran);
29-
plan("test").Dependencies = ["build_c", "build_cpp", "build_fortran"];
30-
3126
if ~isMATLABReleaseOlderThan("R2024a")
3227
plan("check") = matlab.buildtool.tasks.CodeIssuesTask(pkg_name, IncludeSubfolders=true, ...
3328
WarningThreshold=0, Results="CodeIssues.sarif");
@@ -42,6 +37,19 @@
4237
% dummy task to allow "buildtool mex" to build all MEX targets
4338
plan("mex") = matlab.buildtool.Task();
4439
mex_deps = string.empty;
40+
else
41+
td = plan.RootFolder + "/test";
42+
43+
plan("exe:c") = matlab.buildtool.Task(Inputs=td+"/stdout_stderr_c.c", ...
44+
Outputs=td+"/stdout_stderr_c.exe", Actions=@build_exe);
45+
46+
plan("exe:cpp") = matlab.buildtool.Task(Inputs=td+"/stdin_cpp.cpp",...
47+
Outputs=td+"/stdin_cpp.exe", Actions=@build_exe);
48+
49+
plan("exe:fortran") = matlab.buildtool.Task(Inputs=[td + "/stdout_stderr_fortran.f90", td + "/stdin_fortran.f90"],...
50+
Outputs=[td+"/stdout_stderr_fortran.exe", td+"/stdin_fortran.exe"], Actions=@build_exe);
51+
52+
plan("test").Dependencies = "exe";
4553
end
4654

4755
for s = get_mex_sources()
@@ -51,11 +59,8 @@
5159
% name of MEX target function is name of first source file
5260
if isMATLABReleaseOlderThan("R2024b")
5361
mex_name = "mex_" + name;
54-
% specifying .Inputs and .Outputs enables incremental builds
55-
% https://www.mathworks.com/help/matlab/matlab_prog/improve-performance-with-incremental-builds.html
56-
plan(mex_name) = matlab.buildtool.Task(Actions=@(context) legacy_mex(context, compiler_opt, linker_opt));
57-
plan(mex_name).Inputs = src;
58-
plan(mex_name).Outputs = fullfile(bindir, name + "." + mexext());
62+
plan(mex_name) = matlab.buildtool.Task(Inputs=src, Outputs=fullfile(bindir, name + "." + mexext()), ...
63+
Actions=@(context) legacy_mex(context, compiler_opt, linker_opt));
5964
mex_deps(end+1) = mex_name; %#ok<AGROW>
6065
else
6166
plan("mex:" + name) = matlab.buildtool.tasks.MexTask(src, bindir, ...
@@ -96,71 +101,29 @@ function publishTask(context)
96101
end
97102

98103

99-
function subprocess_build_c(context)
100-
101-
td = context.Plan.RootFolder + "/test";
102-
src = td + "/stdout_stderr_c.c";
103-
104-
for s = src
105-
[~, n] = fileparts(s);
106-
exe = fullfile(td, n + ".exe");
107-
if stdlib.get_modtime(s) < stdlib.get_modtime(exe)
108-
continue
109-
end
110-
111-
cmd = get_build_cmd("c++", s);
112-
if isempty(cmd), return, end
113-
cmd = cmd + exe;
114-
disp(cmd)
115-
[r, m] = system(cmd);
116-
if r ~= 0
117-
disp("failed to build TestSubprocess " + exe + " " + m)
118-
end
119-
end
120-
121-
end
122-
123-
124-
function subprocess_build_cpp(context)
104+
function build_exe(context)
125105

126-
td = context.Plan.RootFolder + "/test";
127-
src = [td + "/sleep.cpp", td + "/stdin_cpp.cpp"];
128-
129-
for s = src
130-
[~, n] = fileparts(s);
131-
exe = fullfile(td, n + ".exe");
132-
if stdlib.get_modtime(s) < stdlib.get_modtime(exe)
133-
continue
134-
end
106+
for i = 1:length(context.Task.Inputs)
107+
src = context.Task.Inputs(i);
108+
exe = context.Task.Outputs(i).paths;
109+
exe = exe(1);
135110

136-
cmd = get_build_cmd("c++", s);
137-
if isempty(cmd), return, end
138-
cmd = cmd + exe;
139-
disp(cmd)
140-
[r, m] = system(cmd);
141-
if r ~= 0
142-
disp("failed to build TestSubprocess " + exe + " " + m)
111+
[~,~,ext] = fileparts(src.paths);
112+
switch ext
113+
case ".c", lang = "c";
114+
case ".cpp", lang = "c++";
115+
case ".f90", lang = "fortran";
116+
otherwise, error("unknown code suffix " + ext)
143117
end
144-
end
145118

146-
end
119+
[comp, shell, outFlag] = get_build_cmd(lang);
120+
if isempty(comp), return, end
147121

148-
149-
function subprocess_build_fortran(context)
150-
151-
td = context.Plan.RootFolder + "/test";
152-
src = [td + "/stdout_stderr_fortran.f90", td + "/stdin_fortran.f90"];
153-
154-
for s = src
155-
[~, n] = fileparts(s);
156-
exe = fullfile(td, n + ".exe");
157-
if stdlib.get_modtime(s) < stdlib.get_modtime(exe)
158-
continue
122+
cmd = join([comp, src.paths, outFlag + exe]);
123+
if ~isempty(shell)
124+
cmd = join([shell, "&&", cmd]);
159125
end
160126

161-
cmd = get_build_cmd("Fortran", s);
162-
if isempty(cmd), return, end
163-
cmd = cmd + exe;
164127
disp(cmd)
165128
[r, m] = system(cmd);
166129
if r ~= 0
@@ -171,38 +134,56 @@ function subprocess_build_fortran(context)
171134
end
172135

173136

174-
function cmd = get_build_cmd(lang, src)
137+
function [comp, shell] = get_compiler(lang)
175138

176-
cmd = string.empty;
139+
lang = lower(lang);
177140

178141
co = mex.getCompilerConfigurations(lang);
142+
179143
if isempty(co)
180-
if lang == "Fortran"
181-
fc = getenv("FC");
182-
if isempty(fc)
183-
disp("set FC environment variable to the Fortran compiler executable, or do 'mex -setup fortran' to configure the Fortran compiler")
184-
end
144+
switch lang
145+
case "fortran"
146+
comp = getenv("FC");
147+
if isempty(comp)
148+
disp("set FC environment variable to the Fortran compiler path, or do 'mex -setup fortran'")
149+
end
150+
case "c++"
151+
comp = getenv("CXX");
152+
if isempty(comp)
153+
disp("set CXX environment variable to the C++ compiler path, or do 'mex -setup c++")
154+
end
155+
case "c"
156+
comp = getenv("CC");
157+
if isempty(comp)
158+
disp("set CC environment variable to the C compiler path, or do 'mex -setup c'")
159+
end
160+
otherwise, error("language not known " + lang)
185161
end
186-
disp(lang + " compiler not found")
187-
return
188162
else
189163
comp = co.Details.CompilerExecutable;
190164
end
191165

192-
outFlag = "-o";
193-
shell = string.empty;
194-
msvcLike = ispc && (contains(co.Name, "Visual Studio"));
195-
if msvcLike
166+
if ispc && contains(co.Name, "Visual Studio")
196167
shell = join([strcat('"',string(co.Details.CommandLineShell),'"'), ...
197168
co.Details.CommandLineShellArg], " ");
198-
outFlag = "/Fo" + tempdir + " /link /out:";
169+
else
170+
shell = string.empty;
171+
end
172+
199173
end
200174

201-
cmd = join([comp, src, outFlag]);
175+
176+
function [comp, shell, outFlag] = get_build_cmd(lang)
177+
178+
outFlag = "-o";
179+
180+
[comp, shell] = get_compiler(lang);
181+
202182
if ~isempty(shell)
203-
cmd = join([shell, "&&", cmd]);
183+
outFlag = "/Fo" + tempdir + " /link /out:";
204184
end
205185

186+
206187
end
207188

208189

0 commit comments

Comments
 (0)