Better compiler argument warnings handling (#5076)

The goal of this PR is to display any warnings about compiler arguments,
e.g. the warning about -march=native, somewhere else instead of a toast
notification every time. Feature requested on discord.


![image](https://github.com/compiler-explorer/compiler-explorer/assets/51220084/40a0c670-b2bb-4fae-b98d-937dbeb7d2e6)

![Animation](https://github.com/compiler-explorer/compiler-explorer/assets/51220084/43575608-daa6-487d-9ef9-ca04bdd38a38)

![image](https://github.com/compiler-explorer/compiler-explorer/assets/51220084/551e26e5-1e4f-4802-a68a-fb63e0e5e415)

---------

Co-authored-by: Matt Godbolt <matt@godbolt.org>
This commit is contained in:
Jeremy Rifkin
2023-05-30 22:18:09 -04:00
committed by GitHub
parent 0bc22f8883
commit edcacc0272
11 changed files with 169 additions and 25 deletions

View File

@@ -7,9 +7,9 @@
**Compiler Explorer** is an interactive compiler exploration website. Edit code in C, C++, C#, F#, Rust, Go, D, Haskell, **Compiler Explorer** is an interactive compiler exploration website. Edit code in C, C++, C#, F#, Rust, Go, D, Haskell,
Swift, Pascal, [ispc](https://ispc.github.io/), Python, Java, or any of the other Swift, Pascal, [ispc](https://ispc.github.io/), Python, Java, or any of the other
[30+ supported languages](https://godbolt.org/api/languages), and see how that code looks after being compiled in [30+ supported languages](https://godbolt.org/api/languages), and see how that code looks after being compiled in real
real time. Multiple compilers are supported for each language, many different tools and visualizations are available, time. Multiple compilers are supported for each language, many different tools and visualizations are available, and the
and the UI layout is configurable (thanks to [GoldenLayout](https://www.golden-layout.com/)). UI layout is configurable (thanks to [GoldenLayout](https://www.golden-layout.com/)).
Try out at [godbolt.org](https://godbolt.org), or [run your own local instance](#running-a-local-instance). Try out at [godbolt.org](https://godbolt.org), or [run your own local instance](#running-a-local-instance).
@@ -133,5 +133,5 @@ We would also like to specially thank these people for their contributions to **
- [Joshua Sheard](https://github.com/jsheard) - [Joshua Sheard](https://github.com/jsheard)
- [Andrew Pardoe](https://github.com/AndrewPardoe) - [Andrew Pardoe](https://github.com/AndrewPardoe)
Many [amazing sponsors](https://godbolt.org/#sponsors), both individuals and companies, have helped fund and Many [amazing sponsors](https://godbolt.org/#sponsors), both individuals and companies, have helped fund and promote
promote Compiler Explorer. Compiler Explorer.

View File

@@ -22,6 +22,9 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// TODO(jeremy-rifkin): Use the enum names rather than underlying values in compiler-service.ts and the
// compiler/executer panes
export enum CompilationStatusCode { export enum CompilationStatusCode {
NONE = 0, NONE = 0,
OK = 1, OK = 1,

View File

@@ -423,8 +423,7 @@ export class CompilerService {
.addClass('status-icon fas') .addClass('status-icon fas')
.css('color', this.getColor(status)) .css('color', this.getColor(status))
.toggle(status.code !== 0) .toggle(status.code !== 0)
.prop('aria-label', this.getAriaLabel(status)) .attr('aria-label', this.getAriaLabel(status))
.prop('data-status', status.code)
.toggleClass('fa-spinner fa-spin', status.code === 4) .toggleClass('fa-spinner fa-spin', status.code === 4)
.toggleClass('fa-times-circle', status.code === 3) .toggleClass('fa-times-circle', status.code === 3)
.toggleClass('fa-check-circle', status.code === 1 || status.code === 2); .toggleClass('fa-check-circle', status.code === 1 || status.code === 2);

View File

@@ -1603,7 +1603,6 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
}); });
} }
this.handleCompilationStatus(CompilerService.calculateStatusIcon(result));
this.outputTextCount.text(stdout.length); this.outputTextCount.text(stdout.length);
this.outputErrorCount.text(stderr.length); this.outputErrorCount.text(stderr.length);
if (this.isOutputOpened || (stdout.length === 0 && stderr.length === 0)) { if (this.isOutputOpened || (stdout.length === 0 && stderr.length === 0)) {
@@ -1682,8 +1681,12 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
this.updateButtons(); this.updateButtons();
this.checkForUnwiseArguments(result.compilationOptions, wasCmake ?? false); this.handleCompilationStatus(CompilerService.calculateStatusIcon(result));
this.setCompilationOptionsPopover(result.compilationOptions ? result.compilationOptions.join(' ') : ''); const warnings = this.checkForUnwiseArguments(result.compilationOptions, wasCmake ?? false);
this.setCompilationOptionsPopover(
result.compilationOptions ? result.compilationOptions.join(' ') : '',
warnings,
);
this.checkForHints(result); this.checkForHints(result);
@@ -2365,7 +2368,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
this.fullCompilerName = this.domRoot.find('.full-compiler-name'); this.fullCompilerName = this.domRoot.find('.full-compiler-name');
this.fullTimingInfo = this.domRoot.find('.full-timing-info'); this.fullTimingInfo = this.domRoot.find('.full-timing-info');
this.compilerLicenseButton = this.domRoot.find('.compiler-license'); this.compilerLicenseButton = this.domRoot.find('.compiler-license');
this.setCompilationOptionsPopover(this.compiler ? this.compiler.options : null); this.setCompilationOptionsPopover(this.compiler ? this.compiler.options : null, []);
this.initFilterButtons(); this.initFilterButtons();
@@ -2946,8 +2949,8 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
} }
} }
checkForUnwiseArguments(optionsArray: string[] | undefined, wasCmake: boolean): void { checkForUnwiseArguments(optionsArray: string[] | undefined, wasCmake: boolean) {
if (!this.compiler) return; if (!this.compiler) return [];
if (!optionsArray) optionsArray = []; if (!optionsArray) optionsArray = [];
@@ -2964,19 +2967,17 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
const are = unwiseOptions.length === 1 ? ' is ' : ' are '; const are = unwiseOptions.length === 1 ? ' is ' : ' are ';
const msg = options + names + are + 'not recommended, as behaviour might change based on server hardware.'; const msg = options + names + are + 'not recommended, as behaviour might change based on server hardware.';
const warnings: string[] = [];
if (optionsArray.some(opt => opt === '-flto') && !this.filters.isSet('binary') && !wasCmake) { if (optionsArray.some(opt => opt === '-flto') && !this.filters.isSet('binary') && !wasCmake) {
this.alertSystem.notify('Option -flto is being used without Compile to Binary.', { warnings.push('Option -flto is being used without Compile to Binary.');
group: 'unwiseOption',
collapseSimilar: true,
});
} }
if (unwiseOptions.length > 0) { if (unwiseOptions.length > 0) {
this.alertSystem.notify(msg, { warnings.push(msg);
group: 'unwiseOption',
collapseSimilar: true,
});
} }
return warnings;
} }
updateCompilerInfo(): void { updateCompilerInfo(): void {
@@ -3258,16 +3259,37 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
} }
} }
setCompilationOptionsPopover(content: string | null): void { setCompilationOptionsPopover(content: string | null, warnings: string[]): void {
const infoLine =
'<div class="compiler-arg-warning info">You can configure icon animations in Settings>Compilation</div>\n';
this.prependOptions.popover('dispose'); this.prependOptions.popover('dispose');
this.prependOptions.popover({ this.prependOptions.popover({
content: content || 'No options in use', content:
warnings.map(w => `<div class="compiler-arg-warning">${w}</div>`).join('\n') +
'\n' +
(warnings.length > 0 ? infoLine : '') +
_.escape(content || 'No options in use') +
`\n<div class="compiler-arg-warning-shake-setting"></div>`,
html: true,
template: template:
'<div class="popover' + '<div class="popover' +
(content ? ' compiler-options-popover' : '') + (content ? ' compiler-options-popover' : '') +
'" role="tooltip"><div class="arrow"></div>' + '" role="tooltip"><div class="arrow"></div>' +
'<h3 class="popover-header"></h3><div class="popover-body"></div></div>', '<h3 class="popover-header"></h3><div class="popover-body"></div></div>',
}); });
// TODO: Kind of redundant with compiler-service's handleCompilationStatus and overriding what that function
// does. I hate that the logic is spread out like this. Definitely in need of a refactor.
if (warnings.length > 0) {
this.statusIcon
.removeClass()
.addClass(
'status-icon fa-solid fa-triangle-exclamation compiler-arg-warning-icon' +
(this.settings.shakeStatusIconOnWarnings ? ' shake' : ''),
)
.css('color', '')
.attr('aria-label', 'There are warnings about the compiler arguments that have been provided');
}
} }
setCompilerVersionPopover(version?: {version: string; fullVersion?: string}, notification?: string[] | string) { setCompilerVersionPopover(version?: {version: string; fullVersion?: string}, notification?: string[] | string) {

View File

@@ -1227,6 +1227,7 @@ export class Executor extends Pane<ExecutorState> {
return '#FF1212'; return '#FF1212';
} }
// TODO: Duplicate with compiler-service.ts?
handleCompilationStatus(status: CompilationStatus): void { handleCompilationStatus(status: CompilationStatus): void {
// We want to do some custom styles for the icon, so we don't pass it here and instead do it later // We want to do some custom styles for the icon, so we don't pass it here and instead do it later
CompilerService.handleCompilationStatus(this.statusLabel, null, {compilerOut: 0, ...status}); CompilerService.handleCompilationStatus(this.statusLabel, null, {compilerOut: 0, ...status});
@@ -1237,8 +1238,7 @@ export class Executor extends Pane<ExecutorState> {
.addClass('status-icon fas') .addClass('status-icon fas')
.css('color', this.color(status)) .css('color', this.color(status))
.toggle(status.code !== 0) .toggle(status.code !== 0)
.prop('aria-label', this.ariaLabel(status)) .attr('aria-label', this.ariaLabel(status))
.prop('data-status', status.code)
.toggleClass('fa-spinner fa-spin', status.code === 4) .toggleClass('fa-spinner fa-spin', status.code === 4)
.toggleClass('fa-times-circle', status.code !== 4 && !status.didExecute) .toggleClass('fa-times-circle', status.code !== 4 && !status.didExecute)
.toggleClass('fa-check-circle', status.code !== 4 && status.didExecute); .toggleClass('fa-check-circle', status.code !== 4 && status.didExecute);

View File

@@ -58,6 +58,7 @@ export interface SiteSettings {
editorsFFont: string; editorsFFont: string;
editorsFLigatures: boolean; editorsFLigatures: boolean;
executorCompileOnChange: boolean; executorCompileOnChange: boolean;
shakeStatusIconOnWarnings: boolean;
defaultFontScale?: number; // the font scale widget can check this setting before the default has been populated defaultFontScale?: number; // the font scale widget can check this setting before the default has been populated
formatBase: FormatBase; formatBase: FormatBase;
formatOnCompile: boolean; formatOnCompile: boolean;
@@ -273,6 +274,7 @@ export class Settings {
['.enableCtrlStree', 'enableCtrlStree', true], ['.enableCtrlStree', 'enableCtrlStree', true],
['.enableSharingPopover', 'enableSharingPopover', true], ['.enableSharingPopover', 'enableSharingPopover', true],
['.executorCompileOnChange', 'executorCompileOnChange', true], ['.executorCompileOnChange', 'executorCompileOnChange', true],
['.shakeStatusIconOnWarnings', 'shakeStatusIconOnWarnings', true],
['.formatOnCompile', 'formatOnCompile', false], ['.formatOnCompile', 'formatOnCompile', false],
['.hoverShowAsmDoc', 'hoverShowAsmDoc', true], ['.hoverShowAsmDoc', 'hoverShowAsmDoc', true],
['.hoverShowSource', 'hoverShowSource', true], ['.hoverShowSource', 'hoverShowSource', true],

View File

@@ -1302,3 +1302,57 @@ html[data-theme='pink'] {
overflow: hidden; overflow: hidden;
max-height: 100%; max-height: 100%;
} }
// shamelessly stolen from https://css-tricks.com/snippets/css/shake-css-keyframe-animation/
@keyframes shake {
10%, 90% {
transform: translate3d(calc(var(--shake-amount) * -25%), 0, 0);
}
20%, 80% {
transform: translate3d(calc(var(--shake-amount) * 50%), 0, 0);
}
30%, 50%, 70% {
transform: translate3d(calc(var(--shake-amount) * -1), 0, 0);
}
40%, 60% {
transform: translate3d(var(--shake-amount), 0, 0);
}
}
.shake {
animation: shake 0.82s cubic-bezier(.36, .07, .19, .97) both;
transform: translate3d(0, 0, 0);
}
.compiler-arg-warning-icon {
--shake-amount: 2px;
}
.compiler-arg-warning {
$sidebar-width: 20px;
$border-width: 2px;
margin-left: $sidebar-width;
position: relative;
border: $border-width solid;
padding: 0 5px;
margin-bottom: 5px;
&:before {
position: absolute;
top: -$border-width;
left: -$sidebar-width;
width: $sidebar-width;
height: calc(100% + 2 * $border-width);
border: $border-width solid;
content: "\f071";
color: #292726;
font-family: "Font Awesome 6 Free";
font-weight: 900;
text-align: center;
}
&:first-child {
margin-top: 5px;
}
}

View File

@@ -663,3 +663,24 @@ textarea.form-control {
} }
} }
} }
.compiler-arg-warning-icon {
color: #ffbf3f !important;
}
.compiler-arg-warning {
border-color: #ffbf3f;
&:before {
border-color: #ffbf3f;
background: #ffbf3f;
}
&.info {
border-color: #3f92ff;
&:before {
border-color: #3f92ff;
background: #3f92ff;
content: "\f05a";
color: rgb(20, 21, 22);
}
}
}

View File

@@ -447,3 +447,24 @@ div.argmenuitem span.argdescription {
} }
} }
} }
.compiler-arg-warning-icon {
color: #ff6a10 !important;
}
.compiler-arg-warning {
border-color: #ff6a10;
&:before {
border-color: #ff6a10;
background: #ff6a10;
}
&.info {
border-color: #3f92ff;
&:before {
border-color: #3f92ff;
background: #3f92ff;
content: "\f05a";
color: rgb(20, 21, 22);
}
}
}

View File

@@ -688,3 +688,24 @@ textarea.form-control {
} }
} }
} }
.compiler-arg-warning-icon {
color: #f22 !important;
}
.compiler-arg-warning {
border-color: #f22;
&:before {
border-color: #f22;
background: #f22;
}
&.info {
border-color: #3f92ff;
&:before {
border-color: #3f92ff;
background: #3f92ff;
content: "\f05a";
color: rgb(20, 21, 22);
}
}
}

View File

@@ -109,5 +109,6 @@ mixin input(cls, type, text, style)
b 3s b 3s
+checkbox("formatOnCompile", "Enable formatting on compilation (for supported languages)") +checkbox("formatOnCompile", "Enable formatting on compilation (for supported languages)")
+checkbox("executorCompileOnChange", "Compile executor automatically when arguments change") +checkbox("executorCompileOnChange", "Compile executor automatically when arguments change")
+checkbox("shakeStatusIconOnWarnings", "Shake the status icon on argument warnings")
.modal-footer .modal-footer
button.btn.btn-outline-primary(type="button" data-dismiss="modal") Close button.btn.btn-outline-primary(type="button" data-dismiss="modal") Close