The Grand Reformat (#3643)

* The Grand Reformat

- everything made prettier...literally
- some tweaks to include a few more files, including documentation
- minor changes to format style
- some tiny `// prettier-ignore` changes to keep a few things the way we like them
- a couple of super minor tweaks to embedded document types to ensure they format correctly
This commit is contained in:
Matt Godbolt
2022-05-09 23:13:50 -05:00
committed by GitHub
parent 141fa73521
commit f2c1e0bd31
244 changed files with 4201 additions and 3481 deletions

View File

@@ -1,32 +1,32 @@
--- ---
plugins: plugins:
- eslint-plugin-header - eslint-plugin-header
rules: rules:
header/header: header/header:
- off - off
- line - line
- - pattern: "^ Copyright \\(c\\) \\d{4}, .*$" - - pattern: '^ Copyright \\(c\\) \\d{4}, .*$'
template: " Copyright (c) 2021, Compiler Explorer Authors" template: ' Copyright (c) 2021, Compiler Explorer Authors'
- " All rights reserved." - ' All rights reserved.'
- "" - ''
- " Redistribution and use in source and binary forms, with or without" - ' Redistribution and use in source and binary forms, with or without'
- " modification, are permitted provided that the following conditions are met:" - ' modification, are permitted provided that the following conditions are met:'
- "" - ''
- " * Redistributions of source code must retain the above copyright notice," - ' * Redistributions of source code must retain the above copyright notice,'
- " this list of conditions and the following disclaimer." - ' this list of conditions and the following disclaimer.'
- " * Redistributions in binary form must reproduce the above copyright" - ' * Redistributions in binary form must reproduce the above copyright'
- " notice, this list of conditions and the following disclaimer in the" - ' notice, this list of conditions and the following disclaimer in the'
- " documentation and/or other materials provided with the distribution." - ' documentation and/or other materials provided with the distribution.'
- "" - ''
- " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"" - ' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"'
- " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE" - ' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE'
- " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE" - ' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE'
- " ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE" - ' ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE'
- " LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR" - ' LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR'
- " CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF" - ' CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF'
- " SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS" - ' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS'
- " INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN" - ' INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN'
- " CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)" - ' CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)'
- " 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.'
- 2 - 2

View File

@@ -45,7 +45,7 @@ rules:
import/no-default-export: warn import/no-default-export: warn
import/no-deprecated: warn import/no-deprecated: warn
import/no-mutable-exports: error import/no-mutable-exports: error
import/no-named-as-default-member: off # Far too many things (express, morgan, fs) trip this import/no-named-as-default-member: off # Far too many things (express, morgan, fs) trip this
import/no-self-import: error import/no-self-import: error
import/no-useless-path-segments: error import/no-useless-path-segments: error
import/no-webpack-loader-syntax: error import/no-webpack-loader-syntax: error
@@ -147,7 +147,7 @@ rules:
unicorn/prefer-spread: off unicorn/prefer-spread: off
unicorn/no-lonely-if: off unicorn/no-lonely-if: off
unicorn/no-array-reduce: off unicorn/no-array-reduce: off
unicorn/prefer-array-flat: off # can't turn off yet without tests blowing up; lodash vs underscore? unicorn/prefer-array-flat: off # can't turn off yet without tests blowing up; lodash vs underscore?
unicorn/no-array-callback-reference: off unicorn/no-array-callback-reference: off
unicorn/prefer-switch: off unicorn/prefer-switch: off
unicorn/no-static-only-class: off unicorn/no-static-only-class: off
@@ -162,7 +162,7 @@ globals:
BigInt: true BigInt: true
settings: settings:
node: node:
tryExtensions: [ .js, .ts ] tryExtensions: [.js, .ts]
import/parsers: import/parsers:
"@typescript-eslint/parser": [ .ts, .tsx ] '@typescript-eslint/parser': [.ts, .tsx]
import/resolver: "typescript" import/resolver: 'typescript'

View File

@@ -1,7 +1,7 @@
name: Bug Report name: Bug Report
description: Create a report to help us improve description: Create a report to help us improve
title: "[BUG]: " title: '[BUG]: '
labels: ["bug"] labels: ['bug']
body: body:
- type: textarea - type: textarea
id: description id: description
@@ -50,12 +50,13 @@ body:
required: false required: false
- type: markdown - type: markdown
attributes: attributes:
value: "# System information" value: '# System information'
- type: input - type: input
id: operating-system id: operating-system
attributes: attributes:
label: Operating System label: Operating System
description: If applicable (i.e, an issue with how the site behaves for you) the OS version this bug is happening in description:
If applicable (i.e, an issue with how the site behaves for you) the OS version this bug is happening in
placeholder: Ubuntu Linux 20.04 placeholder: Ubuntu Linux 20.04
validations: validations:
required: false required: false

View File

@@ -1,7 +1,7 @@
name: Compiler request name: Compiler request
description: Request a new compiler description: Request a new compiler
title: "[COMPILER REQUEST]: " title: '[COMPILER REQUEST]: '
labels: ["request", "new-compilers"] labels: ['request', 'new-compilers']
body: body:
- type: input - type: input
id: compiler-name id: compiler-name

View File

@@ -1,7 +1,7 @@
name: Feature request name: Feature request
description: Suggest an idea for the project description: Suggest an idea for the project
title: "[REQUEST]: " title: '[REQUEST]: '
labels: ["request"] labels: ['request']
body: body:
- type: textarea - type: textarea
id: introduction id: introduction
@@ -23,7 +23,9 @@ body:
id: alternatives id: alternatives
attributes: attributes:
label: Describe alternatives you've considered label: Describe alternatives you've considered
description: If applicable, please add a clear and concise description of any alternative solutions or features you've considered. description:
If applicable, please add a clear and concise description of any alternative solutions or features you've
considered.
placeholder: You can pass -E to the compiler flags, but I'd like to easily side-by-side compare placeholder: You can pass -E to the compiler flags, but I'd like to easily side-by-side compare
validations: validations:
required: true required: true

View File

@@ -1,7 +1,7 @@
name: Library request name: Library request
description: Request a new library description: Request a new library
title: "[LIB REQUEST]: " title: '[LIB REQUEST]: '
labels: ["request", "new-libs"] labels: ['request', 'new-libs']
body: body:
- type: input - type: input
id: library-name id: library-name
@@ -15,7 +15,9 @@ body:
id: library-description id: library-description
attributes: attributes:
label: Library description label: Library description
description: A sentence that describes what this library does. It helps us when filling some of the UI elements when adding the library description:
A sentence that describes what this library does. It helps us when filling some of the UI elements when adding
the library
placeholder: GoogleTest is a testing library for C++ placeholder: GoogleTest is a testing library for C++
validations: validations:
required: true required: true

154
.github/labeler.yml vendored
View File

@@ -1,110 +1,110 @@
ui: ui:
- static/**/* - static/**/*
- views/**/* - views/**/*
lang-ada: lang-ada:
- lib/compilers/ada.js - lib/compilers/ada.js
- etc/config/ada.*.properties - etc/config/ada.*.properties
lang-asm: lang-asm:
- lib/compilers/assembly.js - lib/compilers/assembly.js
- lib/compilers/nasm.js - lib/compilers/nasm.js
- lib/compilers/ptxas.js - lib/compilers/ptxas.js
- etc/config/assembly.*.properties - etc/config/assembly.*.properties
lang-c: lang-c:
- lib/compilers/cc65.js - lib/compilers/cc65.js
- lib/compilers/ellcc.js - lib/compilers/ellcc.js
- lib/compilers/ewarm.js - lib/compilers/ewarm.js
- lib/compilers/awavr.js - lib/compilers/awavr.js
- lib/compilers/ppci.js - lib/compilers/ppci.js
- lib/compilers/sdcc.js - lib/compilers/sdcc.js
- lib/compilers/tendra.js - lib/compilers/tendra.js
- etc/config/c.*.properties - etc/config/c.*.properties
lang-c++: lang-c++:
- lib/compilers/ewarm.js - lib/compilers/ewarm.js
- lib/compilers/awavr.js - lib/compilers/awavr.js
- etc/config/c++.*.properties - etc/config/c++.*.properties
lang-c++-opencl: lang-c++-opencl:
- etc/config/cpp_for_opencl.*.properties - etc/config/cpp_for_opencl.*.properties
lang-circle: lang-circle:
- lib/compilers/circle.js - lib/compilers/circle.js
- etc/config/circle.*.properties - etc/config/circle.*.properties
lang-clean: lang-clean:
- lib/compilers/clean.js - lib/compilers/clean.js
- etc/config/clean.*.properties - etc/config/clean.*.properties
lang-cppx: lang-cppx:
- etc/config/cppx?(_blue|_gold).*.properties - etc/config/cppx?(_blue|_gold).*.properties
lang-crystal: lang-crystal:
- lib/compilers/crystal.js - lib/compilers/crystal.js
- etc/config/crystal.*.properties - etc/config/crystal.*.properties
lang-cuda: lang-cuda:
- lib/compilers/nvcc.js - lib/compilers/nvcc.js
- etc/config/cuda.*.properties - etc/config/cuda.*.properties
lang-d: lang-d:
- lib/compilers/dmd.js - lib/compilers/dmd.js
- lib/compilers/ldc.js - lib/compilers/ldc.js
- etc/config/d.*.properties - etc/config/d.*.properties
lang-dotnet: lang-dotnet:
- lib/compilers/dotnet.ts - lib/compilers/dotnet.ts
- lib/asm-parser-dotnet.ts - lib/asm-parser-dotnet.ts
- etc/config/csharp.*.properties - etc/config/csharp.*.properties
- etc/config/fsharp.*.properties - etc/config/fsharp.*.properties
- etc/config/vb.*.properties - etc/config/vb.*.properties
lang-dart: lang-dart:
- lib/compilers/dart.js - lib/compilers/dart.js
- etc/config/dart.*.properties - etc/config/dart.*.properties
lang-fortran: lang-fortran:
- lib/compilers/fortran.js - lib/compilers/fortran.js
- etc/config/fortran.*.properties - etc/config/fortran.*.properties
lang-go: lang-go:
- lib/compilers/golang.js - lib/compilers/golang.js
- etc/config/go.*.properties - etc/config/go.*.properties
lang-haskell: lang-haskell:
- lib/compilers/haskell.js - lib/compilers/haskell.js
- etc/config/haskell.*.properties - etc/config/haskell.*.properties
lang-ispc: lang-ispc:
- lib/compilers/ispc.js - lib/compilers/ispc.js
- etc/config/ispc.*.properties - etc/config/ispc.*.properties
lang-java: lang-java:
- lib/compilers/java.js - lib/compilers/java.js
- etc/config/java.*.properties - etc/config/java.*.properties
lang-kotlin: lang-kotlin:
- lib/compilers/kotlin.js - lib/compilers/kotlin.js
- etc/config/kotlin.*.properties - etc/config/kotlin.*.properties
lang-nim: lang-nim:
- lib/compilers/nim.js - lib/compilers/nim.js
- etc/config/nim.*.properties - etc/config/nim.*.properties
lang-ocaml: lang-ocaml:
- lib/compilers/ocaml.js - lib/compilers/ocaml.js
- etc/config/ocaml.*.properties - etc/config/ocaml.*.properties
lang-opencl-c: lang-opencl-c:
- etc/config/openclc.*.properties - etc/config/openclc.*.properties
lang-pascal: lang-pascal:
- lib/compilers/pascal.js - lib/compilers/pascal.js
- etc/config/pascal.*.properties - etc/config/pascal.*.properties
lang-python: lang-python:
- lib/compilers/python.js - lib/compilers/python.js
- etc/config/python.*.properties - etc/config/python.*.properties
lang-ruby: lang-ruby:
- lib/compilers/ruby.js - lib/compilers/ruby.js
- etc/config/ruby.*.properties - etc/config/ruby.*.properties
lang-rust: lang-rust:
- lib/compilers/rust.js - lib/compilers/rust.js
- etc/config/rust.*.properties - etc/config/rust.*.properties
lang-scala: lang-scala:
- lib/compilers/scala.js - lib/compilers/scala.js
- etc/config/scala.*.properties - etc/config/scala.*.properties
lang-solidity: lang-solidity:
- lib/compilers/solidity.js - lib/compilers/solidity.js
- etc/config/solidity.*.properties - etc/config/solidity.*.properties
lang-swift: lang-swift:
- lib/compilers/swift.js - lib/compilers/swift.js
- etc/config/swift.*.properties - etc/config/swift.*.properties
lang-typescript: lang-typescript:
- lib/compilers/typescript.js - lib/compilers/typescript.js
- etc/config/typescript.*.properties - etc/config/typescript.*.properties
lang-zig: lang-zig:
- lib/compilers/zig.js - lib/compilers/zig.js
- etc/config/zig.*.properties - etc/config/zig.*.properties
documentation: documentation:
- docs/**/* - docs/**/*
- README.md - README.md
- CONTRIBUTING.md - CONTRIBUTING.md

View File

@@ -19,8 +19,8 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v3 uses: peter-evans/create-pull-request@v3
with: with:
title: "[bot] Update browsers list" title: '[bot] Update browsers list'
body: | body: |
Automatic run of `npm run-update-browerslist` which needs to Automatic run of `npm run-update-browerslist` which needs to
be done periodically to keep in-date. be done periodically to keep in-date.
See [here](https://github.com/browserslist/browserslist#browsers-data-updating) for more details. See [here](https://github.com/browserslist/browserslist#browsers-data-updating) for more details.

View File

@@ -9,14 +9,14 @@
# the `language` matrix defined below to confirm you have the correct set of # the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages. # supported CodeQL languages.
# #
name: "CodeQL" name: 'CodeQL'
on: on:
push: push:
branches: [ main, release ] branches: [main, release]
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ main ] branches: [main]
schedule: schedule:
- cron: '22 19 * * 4' - cron: '22 19 * * 4'
@@ -32,37 +32,37 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: [ 'javascript', 'python' ] language: ['javascript', 'python']
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v1
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file. # By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file. # Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main # queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project # and modify them (or add more) to build your code if your project
# uses a compiled language # uses a compiled language
#- run: | #- run: |
# make bootstrap # make bootstrap
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v1

View File

@@ -13,4 +13,4 @@ jobs:
steps: steps:
- uses: actions/labeler@v3 - uses: actions/labeler@v3
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -1,6 +1,6 @@
name: Compiler Explorer name: Compiler Explorer
on: [ push, pull_request ] on: [push, pull_request]
jobs: jobs:
test: test:
@@ -53,7 +53,7 @@ jobs:
deploy: deploy:
if: github.repository_owner == 'compiler-explorer' && github.event_name == 'push' if: github.repository_owner == 'compiler-explorer' && github.event_name == 'push'
needs: [ test, build_dist ] needs: [test, build_dist]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:

View File

@@ -1,6 +1,6 @@
name: Compiler Explorer on Windows name: Compiler Explorer on Windows
on: [ push ] on: [push]
jobs: jobs:
build-and-test: build-and-test:

View File

@@ -62,5 +62,8 @@
<codeStyleSettings language="kotlin"> <codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="yaml">
<option name="SPACE_WITHIN_BRACKETS" value="false" />
</codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>

View File

@@ -33,11 +33,9 @@ newrelic_agent.log
# From .eslintignore # From .eslintignore
# Uninteresting folders (node_modules and dotfiles/dotfolders ignored by default) # Uninteresting folders (node_modules and dotfiles/dotfolders ignored by default)
docs
etc etc
examples examples
out out
views
# Autogenerated files # Autogenerated files
lib/asm-docs/generated/asm-docs-*.js lib/asm-docs/generated/asm-docs-*.js

View File

@@ -5,9 +5,10 @@ module.exports = {
arrowParens: 'avoid', arrowParens: 'avoid',
tabWidth: 4, tabWidth: 4,
bracketSpacing: false, bracketSpacing: false,
proseWrap: 'always',
overrides: [ overrides: [
{ {
files: '*.{yml,json}', files: '*.{yml,json,md}',
options: { options: {
tabWidth: 2, tabWidth: 2,
}, },

View File

@@ -1,5 +1,6 @@
Currently, the people referred to when the documentation or policies mention Currently, the people referred to when the documentation or policies mention the administration team of Compiler
the administration team of Compiler Explorer are: Explorer are:
- [Matt Godbolt](https://xania.org) - [Matt Godbolt](https://xania.org)
- [Rubén Rincón](https://rinconblanco.es) - [Rubén Rincón](https://rinconblanco.es)
- [Patrick Quist](https://github.com/partouf) - [Patrick Quist](https://github.com/partouf)
@@ -8,6 +9,7 @@ Currently, the people referred to when the documentation or policies mention
--- ---
Additionally, these people have been immensely helpful in the development of Compiler Explorer: Additionally, these people have been immensely helpful in the development of Compiler Explorer:
- [Jared Wyles](https://github.com/jaredwy) - [Jared Wyles](https://github.com/jaredwy)
- [Chedy Najjar](https://github.com/CppChedy) - [Chedy Najjar](https://github.com/CppChedy)
- [Simon Brand](https://blog.tartanllama.xyz/) - [Simon Brand](https://blog.tartanllama.xyz/)

View File

@@ -4,73 +4,60 @@
## Our Pledge ## Our Pledge
In the interest of fostering an open and welcoming environment, we as In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make
contributors and maintainers pledge to make participation in our project participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
and our community a harassment-free experience for everyone, regardless of age, disability, ethnicity, gender identity, and expression, level of experience, nationality, personal appearance, race,
body size, disability, ethnicity, gender identity, and expression, religion, or sexual identity and orientation.
level of experience, nationality, personal appearance, race, religion,
or sexual identity and orientation.
## Our Standards ## Our Standards
Examples of behavior that contributes to creating a positive environment include: Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language. - Using welcoming and inclusive language.
* Being respectful of differing viewpoints and experiences. - Being respectful of differing viewpoints and experiences.
* Gracefully accepting constructive criticism. - Gracefully accepting constructive criticism.
* Focusing on what is best for the community. - Focusing on what is best for the community.
* Showing empathy towards other community members. - Showing empathy towards other community members.
Examples of **unacceptable** behavior by participants include: Examples of **unacceptable** behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances. - The use of sexualized language or imagery and unwelcome sexual attention or advances.
* Trolling, insulting/derogatory comments, and personal or political attacks. - Trolling, insulting/derogatory comments, and personal or political attacks.
* Public or private harassment. - Public or private harassment.
* Publishing others' private information, such as a physical or electronic address, - Publishing others' private information, such as a physical or electronic address, without explicit permission.
without explicit permission. - Other conduct which could reasonably be considered inappropriate in a professional setting.
* Other conduct which could reasonably be considered inappropriate in a
professional setting.
## Our Responsibilities ## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take
behavior and are expected to take appropriate and fair corrective action in appropriate and fair corrective action in response to any instances of unacceptable behavior.
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
reject comments, commits, code, wiki edits, issues, and other contributions issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
that are not aligned to this Code of Conduct, or to ban contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
temporarily or permanently any contributor for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Scope ## Scope
This Code of Conduct applies both within project spaces and in public spaces This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
when an individual is representing the project or its community. Examples of project or its community. Examples of representing a project or community include using an official project e-mail
representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline
address, posting via an official social media account, or acting as event. Representation of a project may be further defined and clarified by the project maintainers.
an appointed representative at an online or offline event.
Representation of a project may be further defined and clarified by the project
maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project owner at
reported by contacting the project owner at [matt@godbolt.org](mailto:matt@godbolt.org). The project team will review and investigate all complaints, and will
[matt@godbolt.org](mailto:matt@godbolt.org). The project team will review respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain
and investigate all complaints, and will respond in a way that it deems confidentiality concerning the reporter of an incident. Further details of specific enforcement policies may be posted
appropriate to the circumstances. The project team is obligated to maintain separately.
confidentiality concerning the reporter of an incident. Further details of
specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
faith may face temporary or permanent repercussions as determined by other repercussions as determined by other members of the project's leadership.
members of the project's leadership.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at
version 1.4, available at [contributor-covenant.org/version/1/4][version] [contributor-covenant.org/version/1/4][version]
[homepage]: https://www.contributor-covenant.org/ [homepage]: https://www.contributor-covenant.org/
[version]: https://www.contributor-covenant.org/version/1/4/ [version]: https://www.contributor-covenant.org/version/1/4/

View File

@@ -1,94 +1,78 @@
# Contributing to Compiler Explorer # Contributing to Compiler Explorer
First off, if you're reading this: thank you! Even considering contributing to First off, if you're reading this: thank you! Even considering contributing to **Compiler Explorer** is very much
**Compiler Explorer** is very much appreciated! appreciated! Before we go too far, an apology: **Compiler Explorer** grew out of a bit of hacky JavaScript into a pretty
Before we go too far, an apology: **Compiler Explorer** grew out of a bit of large and well-used project pretty quickly. Not all the code was originally well-written or well-tested. Please be
hacky JavaScript into a pretty large and well-used project pretty quickly. forgiving of that.
Not all the code was originally well-written or well-tested.
Please be forgiving of that.
**Compiler Explorer** follows a [Code of Conduct](CODE_OF_CONDUCT.md) which **Compiler Explorer** follows a [Code of Conduct](CODE_OF_CONDUCT.md) which aims to foster an open and welcoming
aims to foster an open and welcoming environment. environment.
# Where to start # Where to start
We have labeled issues which should be easy to do that you can find [here](https://github.com/compiler-explorer/compiler-explorer/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) We have labeled issues which should be easy to do that you can find
[here](https://github.com/compiler-explorer/compiler-explorer/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
If you have any questions, don't hesitate: [Contact us]. If you have any questions, don't hesitate: [Contact us].
If there is something you would like to do yourself, it might help to make an issue so people can weigh in and point you in the right direction. If there is something you would like to do yourself, it might help to make an issue so people can weigh in and point you
in the right direction.
## Node version ## Node version
**Compiler Explorer** currently targets [Node.js](https://nodejs.org/) LTS version 16
so it's better if you do so as well when testing your changes locally. **Compiler Explorer** currently targets [Node.js](https://nodejs.org/) LTS version 16 so it's better if you do so as
well when testing your changes locally.
## In brief ## In brief
* Make your changes, trying to stick to the style and format where possible.
* We use [ESLint](https://eslint.org/) to ensure a consistent code base - Make your changes, trying to stick to the style and format where possible.
and PRs won't pass unless it detects no errors. - We use [ESLint](https://eslint.org/) to ensure a consistent code base and PRs won't pass unless it detects no
* Running `make lint` will run the linter, which will auto-fix everything errors.
it can and report back any errors and warnings. - Running `make lint` will run the linter, which will auto-fix everything it can and report back any errors and
* If you're adding a new server-side component, please do your best to add a test to warnings.
cover it. For client-side changes that's trickier. - If you're adding a new server-side component, please do your best to add a test to cover it. For client-side changes
* Tests should run automatically as a pre-commit step. that's trickier.
_You can disable this check with `git commit --no-verify` if needed_. - Tests should run automatically as a pre-commit step. _You can disable this check with `git commit --no-verify` if
* You can run `make check` to run both the linter and the code tests needed_.
* Do a smoke test: - You can run `make check` to run both the linter and the code tests
Run `make` and ensure the site works as you'd expect. Concentrate on the - Do a smoke test: Run `make` and ensure the site works as you'd expect. Concentrate on the areas you'd expect to have
areas you'd expect to have changed, but if you can, click about generally to changed, but if you can, click about generally to help check you haven't unintentionally broken something else
help check you haven't unintentionally broken something else - Submit a Pull Request.
* Submit a Pull Request.
## Basic code layout ## Basic code layout
Code is separated into server-side code and client-side code. Code is separated into server-side code and client-side code. All dependencies (server and client side) are installed
All dependencies (server and client side) are installed via `package.json`. via `package.json`. _Server code_ is in `app.js` and in the `lib` directory. _Client code_ is all in the `static`
_Server code_ is in `app.js` and in the `lib` directory. directory.
_Client code_ is all in the `static` directory.
In the server code, the `app.js` sets up a basic `express` In the server code, the `app.js` sets up a basic `express` middleware-driven web server, delegating to the various
middleware-driven web server, delegating to the various compiler backends in compiler backends in `lib/compilers/`. All of them inherit from `lib/base-compiler.js` which does most of the work of
`lib/compilers/`. All of them inherit from `lib/base-compiler.js` which does running compilers, then parsing the output and forming a JSON object to send to the client. Any assembly parsing is done
most of the work of running compilers, then parsing the output and forming a in the `lib/asm-parser.js`, and similar, files.
JSON object to send to the client. Any assembly parsing is done in the
`lib/asm-parser.js`, and similar, files.
In the client code, [GoldenLayout](https://www.golden-layout.com/) is used as In the client code, [GoldenLayout](https://www.golden-layout.com/) is used as the container. If you look at some
the container. If you look at some components like the components like the `static/compiler.js`, you'll see the general flow. Any state stored makes it into the URL, so be
`static/compiler.js`, you'll see the general flow. careful not to stash anything too big in there.
Any state stored makes it into the URL, so be careful not to stash
anything too big in there.
The client code follows GoldenLayout's message-based system: The client code follows GoldenLayout's message-based system: no component has a reference to any other and everything is
no component has a reference to any other and everything is done via messages. done via messages. This will allow us to use pop-out windows, if we ever need to, as the messages are JSON-serializable
This will allow us to use pop-out windows, if we ever need to, as the messages between separate windows.
are JSON-serializable between separate windows.
## Editing flow ## Editing flow
The recommended way to work on **Compiler Explorer** is to just run `make dev` The recommended way to work on **Compiler Explorer** is to just run `make dev` and let the automatic reloading do its
and let the automatic reloading do its magic. magic. Any changes to the server code will cause the server to reload, and any changes to the client code will be
Any changes to the server code will cause the server to reload, and any changes reflected upon a page reload. This makes for a pretty quick turnaround. Note that a current issue makes every project
to the client code will be reflected upon a page reload. media asset to be locally unavailable. We will hopefully fix this in the near future.
This makes for a pretty quick turnaround.
Note that a current issue makes every project media asset to be locally
unavailable. We will hopefully fix this in the near future.
## Gotchas ## Gotchas
* New client-side code should preferably be written in TypeScript, - New client-side code should preferably be written in TypeScript, but we will always accept js code too. Be aware that
but we will always accept js code too. Be aware that in that case, in that case, you must stick to **ES5** (so no `let` or arrow operators) js code. Sadly there are still enough users
you must stick to **ES5** (so no `let` or arrow operators) js code. out there on old browsers. Note that this restriction does not apply to the server side code, in which you can use all
Sadly there are still enough users out there on old browsers. the cool features you want. In lieu of ES6 features, [Underscore.js](https://underscorejs.org/) is available as a way
Note that this restriction does not apply to the server side code, to bridge the feature gap. The library is available both in the client and server code.
in which you can use all the cool features you want. - Be aware that **Compiler Explorer** runs on a cluster on the live site. No local state is kept between invocations,
In lieu of ES6 features, [Underscore.js](https://underscorejs.org/) is available and the user's next request will likely hit a different node in the cluster, so don't rely on any in-memory state.
as a way to bridge the feature gap. The library is available both
in the client and server code.
* Be aware that **Compiler Explorer** runs on a cluster on the live site.
No local state is kept between invocations, and the user's next request will
likely hit a different node in the cluster, so don't rely on
any in-memory state.
[Contact us]: README.md#contact-us [contact us]: README.md#contact-us

131
README.md
View File

@@ -5,102 +5,98 @@
# Compiler Explorer # Compiler Explorer
**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 **Compiler Explorer** is an interactive compiler exploration website. Edit code in C, C++, C#, F#, Rust, Go, D, Haskell,
or in any of the other [30+ supported languages](https://godbolt.org/api/languages), and see how that code looks after being compiled in real time. Swift, Pascal, [ispc](https://ispc.github.io/), Python, Java or in any of the other
Multiple compilers are supported for each language, many different tools and visualisations are available, and the UI layout [30+ supported languages](https://godbolt.org/api/languages), and see how that code looks after being compiled in real
is configurable (thanks to [GoldenLayout](https://www.golden-layout.com/)). time. Multiple compilers are supported for each language, many different tools and visualisations are available, and the
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).
**Compiler Explorer** follows a [Code of Conduct](CODE_OF_CONDUCT.md) which **Compiler Explorer** follows a [Code of Conduct](CODE_OF_CONDUCT.md) which aims to foster an open and welcoming
aims to foster an open and welcoming environment. environment.
**Compiler Explorer** was started in 2012 to show how C++ constructs translated to assembly code. It started out as a **Compiler Explorer** was started in 2012 to show how C++ constructs translated to assembly code. It started out as a
`tmux` session with `vi` running in one pane and `watch gcc -S foo.cc -o -` running in the other. `tmux` session with `vi` running in one pane and `watch gcc -S foo.cc -o -` running in the other.
Since then, it has become a public website serving around [3,000,000 compilations per week](https://www.stathat.com/cards/Tk5csAWI0O7x). Since then, it has become a public website serving around
[3,000,000 compilations per week](https://www.stathat.com/cards/Tk5csAWI0O7x).
You can financially support [this project on Patreon](https://patreon.com/mattgodbolt), You can financially support [this project on Patreon](https://patreon.com/mattgodbolt),
[GitHub](https://github.com/sponsors/mattgodbolt/), [Paypal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=KQWQZ7GPY2GZ6&item_name=Compiler+Explorer+development&currency_code=USD&source=url), or by [GitHub](https://github.com/sponsors/mattgodbolt/),
buying cool gear on the [Compiler Explorer store](https://shop.spreadshirt.com/compiler-explorer/). [Paypal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=KQWQZ7GPY2GZ6&item_name=Compiler+Explorer+development&currency_code=USD&source=url),
or by buying cool gear on the [Compiler Explorer store](https://shop.spreadshirt.com/compiler-explorer/).
## Using Compiler Explorer ## Using Compiler Explorer
### FAQ ### FAQ
There is now a FAQ section [in the repository wiki](https://github.com/compiler-explorer/compiler-explorer/wiki/FAQ). There is now a FAQ section [in the repository wiki](https://github.com/compiler-explorer/compiler-explorer/wiki/FAQ). If
If your question is not present, please contact us as described below, so we can help you. your question is not present, please contact us as described below, so we can help you. If you find that the FAQ is
If you find that the FAQ is lacking some important point, please free to contribute to it and/or ask us to clarify it. lacking some important point, please free to contribute to it and/or ask us to clarify it.
### Videos ### Videos
There are a number of videos that showcase some features of Compiler Explorer: There are a number of videos that showcase some features of Compiler Explorer:
* [Presentation for CppCon 2019 about the project](https://www.youtube.com/watch?v=kIoZDUd5DKw) - [Presentation for CppCon 2019 about the project](https://www.youtube.com/watch?v=kIoZDUd5DKw)
* [Older 2 part series of videos](https://www.youtube.com/watch?v=4_HL3PH4wDg) which go into a bit more detail - [Older 2 part series of videos](https://www.youtube.com/watch?v=4_HL3PH4wDg) which go into a bit more detail into the
into the more obscure features. more obscure features.
* [Just Enough Assembly for Compiler Explorer](https://youtu.be/QLolzolunJ4): Practical introduction to Assembly with a focus on usage on Compiler Explorer, from CppCon 2021. - [Just Enough Assembly for Compiler Explorer](https://youtu.be/QLolzolunJ4): Practical introduction to Assembly with a
* [Playlist: Compiler Explorer](https://www.youtube.com/playlist?list=PL2HVqYf7If8dNYVN6ayjB06FPyhHCcnhG): A collection of videos discussing Compiler Explorer; using it, installing it, what it's for, etc. focus on usage on Compiler Explorer, from CppCon 2021.
- [Playlist: Compiler Explorer](https://www.youtube.com/playlist?list=PL2HVqYf7If8dNYVN6ayjB06FPyhHCcnhG): A collection
of videos discussing Compiler Explorer; using it, installing it, what it's for, etc.
A [Road map](docs/Roadmap.md) is available which gives a little insight into A [Road map](docs/Roadmap.md) is available which gives a little insight into the future plans for **Compiler Explorer**.
the future plans for **Compiler Explorer**.
## Developing ## Developing
**Compiler Explorer** is written in [Node.js](https://nodejs.org/). **Compiler Explorer** is written in [Node.js](https://nodejs.org/).
Assuming you have a compatible version of `node` installed, on Linux simply running Assuming you have a compatible version of `node` installed, on Linux simply running `make` ought to get you up and
`make` ought to get you up and running with an Explorer running on port 10240 running with an Explorer running on port 10240 on your local machine:
on your local machine: [http://localhost:10240/](http://localhost:10240/). If this doesn't work for you, please contact [http://localhost:10240/](http://localhost:10240/). If this doesn't work for you, please contact us, as we consider it
us, as we consider it important you can quickly and easily get running. important you can quickly and easily get running. Currently, **Compiler Explorer** requires
Currently, **Compiler Explorer** [`node` 16 _(LTS version)_](CONTRIBUTING.md#node-version) installed, either on the path or at `NODE_DIR` (an environment
requires [`node` 16 _(LTS version)_](CONTRIBUTING.md#node-version) installed, either on the path or at `NODE_DIR` variable or `make` parameter).
(an environment variable or `make` parameter).
Running with `make EXTRA_ARGS='--language LANG'` will allow you to load Running with `make EXTRA_ARGS='--language LANG'` will allow you to load `LANG` exclusively, where `LANG` is one for the
`LANG` exclusively, where `LANG` is one for the language ids/aliases defined language ids/aliases defined in `lib/languages.js`. For example, to only run **Compiler Explorer** with C++ support,
in `lib/languages.js`. For example, to only run **Compiler Explorer** with C++ support, you'd run you'd run `make EXTRA_ARGS='--language c++'`. The `Makefile` will automatically install all the third party libraries
`make EXTRA_ARGS='--language c++'`. The `Makefile` will automatically install all the needed to run; using `npm` to install server-side and client side components.
third party libraries needed to run; using `npm` to install server-side and
client side components.
For development, we suggest using `make dev` to enable some useful features, For development, we suggest using `make dev` to enable some useful features, such as automatic reloading on file changes
such as automatic reloading on file changes and shorter startup times. and shorter startup times.
You can also use `npm run dev` to run if `make dev` doesn't work on your machine. You can also use `npm run dev` to run if `make dev` doesn't work on your machine.
Some languages need extra tools to demangle them, e.g. `rust`, `d`, or `haskell`. Some languages need extra tools to demangle them, e.g. `rust`, `d`, or `haskell`. Such tools are kept separately in the
Such tools are kept separately in the [tools repo](https://github.com/compiler-explorer/compiler-explorer-tools).
[tools repo](https://github.com/compiler-explorer/compiler-explorer-tools).
Configuring compiler explorer is achieved via configuration files in the `etc/config` directory. Values are Configuring compiler explorer is achieved via configuration files in the `etc/config` directory. Values are `key=value`.
`key=value`. Options in a `{type}.local.properties` file (where `{type}` is `c++` or similar) override anything in the Options in a `{type}.local.properties` file (where `{type}` is `c++` or similar) override anything in the
`{type}.defaults.properties` file. There is a `.gitignore` file to ignore `*.local.*` files, so these won't be checked `{type}.defaults.properties` file. There is a `.gitignore` file to ignore `*.local.*` files, so these won't be checked
into git, and you won't find yourself fighting with updated versions when you `git pull`. For more information see into git, and you won't find yourself fighting with updated versions when you `git pull`. For more information see
[Adding a Compiler](docs/AddingACompiler.md). [Adding a Compiler](docs/AddingACompiler.md).
Check [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed information about how you can contribute to **Compiler Explorer**, Check [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed information about how you can contribute to **Compiler
and the [docs](./docs) folder for specific details regarding various things you might want to do, Explorer**, and the [docs](./docs) folder for specific details regarding various things you might want to do, such as
such as how to add new compilers or languages to the site. how to add new compilers or languages to the site.
### Running a local instance ### Running a local instance
If you want to point it at your own GCC or similar binaries, either edit the If you want to point it at your own GCC or similar binaries, either edit the `etc/config/LANG.defaults.properties` or
`etc/config/LANG.defaults.properties` or else make a new one with else make a new one with the name `LANG.local.properties`, substituting `LANG` as needed. `*.local.properties` files
the name `LANG.local.properties`, substituting `LANG` as needed. have the highest priority when loading properties.
`*.local.properties` files have the highest priority when loading properties.
When running in a corporate setting the URL shortening service can be replaced When running in a corporate setting the URL shortening service can be replaced by an internal one if the default storage
by an internal one if the default storage driver isn't appropriate for your driver isn't appropriate for your environment. To do this, add a new module in `lib/shortener/myservice.js` and set the
environment. To do this, add a new module in `lib/shortener/myservice.js` and `urlShortenService` variable in configuration. This module should export a single function, see the
set the `urlShortenService` variable in configuration. This module should [tinyurl module](lib/shortener/tinyurl.js) for an example.
export a single function, see the [tinyurl module](lib/shortener/tinyurl.js)
for an example.
### RESTful API ### RESTful API
There's a simple restful API that can be used to do compiles to asm and to There's a simple restful API that can be used to do compiles to asm and to list compilers.
list compilers.
You can find the API documentation [here](docs/API.md). You can find the API documentation [here](docs/API.md).
@@ -108,7 +104,8 @@ You can find the API documentation [here](docs/API.md).
We run a [Compiler Explorer Discord](https://discord.gg/B5WacA7), which is a place to discuss using or developing We run a [Compiler Explorer Discord](https://discord.gg/B5WacA7), which is a place to discuss using or developing
Compiler Explorer. We also have a presence on the [cpplang](https://cppalliance.org/slack/) Slack channel Compiler Explorer. We also have a presence on the [cpplang](https://cppalliance.org/slack/) Slack channel
`#compiler_explorer` and we have [a public mailing list](https://groups.google.com/forum/#!forum/compiler-explorer-discussion). `#compiler_explorer` and we have
[a public mailing list](https://groups.google.com/forum/#!forum/compiler-explorer-discussion).
There's a development channel on the discord, and also a There's a development channel on the discord, and also a
[development mailing list](https://groups.google.com/forum/#!forum/compiler-explorer-development). [development mailing list](https://groups.google.com/forum/#!forum/compiler-explorer-development).
@@ -118,20 +115,18 @@ Feel free to raise an issue on [github](https://github.com/compiler-explorer/com
## Credits ## Credits
**Compiler Explorer** is maintained by the awesome people listed in the **Compiler Explorer** is maintained by the awesome people listed in the [AUTHORS](AUTHORS.md) file.
[AUTHORS](AUTHORS.md) file.
We would like to thank the contributors listed in the We would like to thank the contributors listed in the [CONTRIBUTORS](CONTRIBUTORS.md) file, who have helped shape
[CONTRIBUTORS](CONTRIBUTORS.md) file, who have helped shape **Compiler Explorer**. **Compiler Explorer**.
We would also like to specially thank these people for their contributions to We would also like to specially thank these people for their contributions to **Compiler Explorer**:
**Compiler Explorer**:
- [Gabriel Devillers](https://github.com/voxelf) - [Gabriel Devillers](https://github.com/voxelf) (_while working for [Kalray](http://www.kalrayinc.com/)_)
(_while working for [Kalray](http://www.kalrayinc.com/)_)
- [Johan Engelen](https://github.com/JohanEngelen) - [Johan Engelen](https://github.com/JohanEngelen)
- [Joshua Sheard](https://github.com/jsheard) - [Joshua Sheard](https://github.com/jsheard)
- [Marc Poulhiès](https://github.com/dkm) - [Marc Poulhiès](https://github.com/dkm)
- [Andrew Pardoe](https://github.com/AndrewPardoe) - [Andrew Pardoe](https://github.com/AndrewPardoe)
A number of [amazing sponsors](https://godbolt.org/#sponsors), both individuals and companies, have helped fund and A number of [amazing sponsors](https://godbolt.org/#sponsors), both individuals and companies, have helped fund and
promote Compiler Explorer. promote Compiler Explorer.

View File

@@ -1,16 +1,15 @@
# Security Policy # Security Policy
Compiler Explorer allows remote users to compile and, if configured, execute Compiler Explorer allows remote users to compile and, if configured, execute code. We take security seriously, and
code. We take security seriously, and encourage users to promptly report encourage users to promptly report security vulnerabilities they find.
security vulnerabilities they find.
## Reporting a Vulnerability ## Reporting a Vulnerability
If the issue can be reported without revealing exploitable specifics, please If the issue can be reported without revealing exploitable specifics, please file
file [an issue](https://github.com/compiler-explorer/compiler-explorer/issues/new/choose) as a bug. [an issue](https://github.com/compiler-explorer/compiler-explorer/issues/new/choose) as a bug.
Please email matt@godbolt.org with specifics, or if the bug can't be reported publically Please email matt@godbolt.org with specifics, or if the bug can't be reported publically without leaving an obvious
without leaving an obvious exploit in the public eye. exploit in the public eye.
We expect to get back within a day or two. If you don't hear from us, please do ping us again, We expect to get back within a day or two. If you don't hear from us, please do ping us again, or reach out to us on the
or reach out to us on the [Discord](https://discord.gg/wFXUwDp). [Discord](https://discord.gg/wFXUwDp).

View File

@@ -1,6 +1,6 @@
function runFrontendTest(name) { function runFrontendTest(name) {
it(name, () => { it(name, () => {
cy.window().then((win) => { cy.window().then(win => {
return win.compilerExplorerFrontendTesting.run(name); return win.compilerExplorerFrontendTesting.run(name);
}); });
}); });

View File

@@ -1,65 +1,59 @@
# RESTful API # RESTful API
There's a simple restful API that can be used to do compiles to asm and to There's a simple restful API that can be used to do compiles to asm and to list compilers. In general all handlers live
list compilers. In general all handlers live in `/api/*` endpoints, will in `/api/*` endpoints, will accept JSON or text in POSTs, and will return text or JSON responses depending on the
accept JSON or text in POSTs, and will return text or JSON responses depending request's `Accept` header.
on the request's `Accept` header.
At a later date there may be some form of rate-limiting: At a later date there may be some form of rate-limiting: currently, requests will be queued and dealt with in the same
currently, requests will be queued and dealt with in the same way interactive way interactive requests are done for the main site. Authentication might be required at some point in the future (for
requests are done for the main site. Authentication might be required at some the main **Compiler Explorer** site anyway).
point in the future (for the main **Compiler Explorer** site anyway).
## Endpoints ## Endpoints
### `GET /api/languages` - return a list of languages ### `GET /api/languages` - return a list of languages
Returns a list of the currently supported languages, as pairs of languages IDs Returns a list of the currently supported languages, as pairs of languages IDs and their names.
and their names.
### `GET /api/compilers` - return a list of compilers ### `GET /api/compilers` - return a list of compilers
Returns a list of compilers. In text form, there's a simple formatting of the Returns a list of compilers. In text form, there's a simple formatting of the ID of the compiler, its description and
ID of the compiler, its description and its language ID. In JSON, all the its language ID. In JSON, all the information is returned as an array of compilers, with the `id` key being the primary
information is returned as an array of compilers, with the `id` key being the identifier of each compiler.
primary identifier of each compiler.
Due to the amount of compilers and information available through this api call, Due to the amount of compilers and information available through this api call, by default you will only get these
by default you will only get these fields per compiler: fields per compiler: `['id', 'name', 'lang', 'compilerType', 'semver', 'extensions', 'monaco']`
`['id', 'name', 'lang', 'compilerType', 'semver', 'extensions', 'monaco']`
If you require different fields, you can specify them by adding `?fields=field1,field2,field3` If you require different fields, you can specify them by adding `?fields=field1,field2,field3` to your query.
to your query.
To see all the available fields, you can use `?fields=all`. It is not recommended using this by default. To see all the available fields, you can use `?fields=all`. It is not recommended using this by default.
### `GET /api/compilers/<language-id>` - return a list of compilers with matching language ### `GET /api/compilers/<language-id>` - return a list of compilers with matching language
Returns a list of compilers for the provided language id. In text form, Returns a list of compilers for the provided language id. In text form, there's a simple formatting of the ID of the
there's a simple formatting of the ID of the compiler, its description and its compiler, its description and its language ID. In JSON, all the information is returned as an array of compilers, with
language ID. In JSON, all the information is returned as an array of compilers, the `id` key being the primary identifier of each compiler.
with the `id` key being the primary identifier of each compiler.
The same field restrictions apply as with `GET /api/compilers` The same field restrictions apply as with `GET /api/compilers`
### `GET /api/libraries/<language-id>` - return a list of libraries available with for a language ### `GET /api/libraries/<language-id>` - return a list of libraries available with for a language
Returns a list of libraries and library versions available for the provided language id. Returns a list of libraries and library versions available for the provided language id. This request only returns data
This request only returns data in JSON. in JSON.
You can use the given include paths to supply in the userArguments for compilation. *(deprecated)* You can use the given include paths to supply in the userArguments for compilation. _(deprecated)_
You will need the library id's, and the version id's to supply to **compile** if you want to include libraries during compilation. You will need the library id's, and the version id's to supply to **compile** if you want to include libraries during
compilation.
### `GET /api/shortlinkinfo/<linkid>` - return information about a given link ### `GET /api/shortlinkinfo/<linkid>` - return information about a given link
Returns information like Sourcecode, Compiler settings and libraries for a given link id. Returns information like Sourcecode, Compiler settings and libraries for a given link id. This request only returns data
This request only returns data in JSON. in JSON.
### `POST /api/compiler/<compiler-id>/compile` - perform a compilation ### `POST /api/compiler/<compiler-id>/compile` - perform a compilation
To specify a compilation request as a JSON document, post it as the appropriate To specify a compilation request as a JSON document, post it as the appropriate type and send an object of the form:
type and send an object of the form:
```JSON ```JSON
{ {
"source": "<Source-to-compile>", "source": "<Source-to-compile>",
@@ -94,6 +88,7 @@ To specify a compilation request as a JSON document, post it as the appropriate
``` ```
Execution Only request example: Execution Only request example:
```JSON ```JSON
{ {
"source": "int main () { return 1; }", "source": "int main () { return 1; }",
@@ -120,27 +115,26 @@ Execution Only request example:
} }
``` ```
The filters are a JSON object with `true`/`false` values. If not supplied, The filters are a JSON object with `true`/`false` values. If not supplied, defaults are used. If supplied, the provided
defaults are used. If supplied, the provided filters override their default filters override their default values. The `compilerOptions` is used to pass extra arguments to the back end, and is
values. The `compilerOptions` is used to pass extra arguments to the back end, probably not useful for most REST users.
and is probably not useful for most REST users.
To force a cache bypass, set `bypassCache` in the root of the request to `true`. To force a cache bypass, set `bypassCache` in the root of the request to `true`.
Filters include `binary`, `labels`, `intel`, `directives` and Filters include `binary`, `labels`, `intel`, `directives` and `demangle`, which correspond to the UI buttons on the HTML
`demangle`, which correspond to the UI buttons on the HTML version. version.
With the tools array you can ask CE to execute certain tools available for With the tools array you can ask CE to execute certain tools available for the current compiler, and also supply
the current compiler, and also supply arguments for this tool. arguments for this tool.
Libraries can be marked to have their directories available when including Libraries can be marked to have their directories available when including their header files. The can be listed by
their header files. The can be listed by supplying the library ids and versions in an array. supplying the library ids and versions in an array. The id's to supply can be found with the
The id's to supply can be found with the `/api/libraries/<language-id>` `/api/libraries/<language-id>`
### `GET /api/formats` - return available code formatters ### `GET /api/formats` - return available code formatters
Returns a list of code formatters. The API returns an array of formatter objects Returns a list of code formatters. The API returns an array of formatter objects which have the following object
which have the following object structure: structure:
```JSON ```JSON
{ {
@@ -178,8 +172,7 @@ The returned JSON body has the following object structure:
} }
``` ```
In cases of internal code formatter failure an additional field named `throw` In cases of internal code formatter failure an additional field named `throw` is also provided and set to true.
is also provided and set to true.
# Non-REST API's # Non-REST API's
@@ -187,12 +180,10 @@ In cases of internal code formatter failure an additional field named `throw`
This is same endpoint as for compilation using JSON. This is same endpoint as for compilation using JSON.
A text compilation request has the source as the body of the post, and uses A text compilation request has the source as the body of the post, and uses query parameters to pass the options and
query parameters to pass the options and filters. Filters are supplied as a filters. Filters are supplied as a comma-separated string. Use the query parameter `filters=XX` to set the filters
comma-separated string. Use the query parameter `filters=XX` to set the directly, else `addFilters=XX` to add a filter to defaults, or `removeFilters` to remove from defaults. Compiler
filters directly, else `addFilters=XX` to add a filter to defaults, parameters should be passed as `options=-O2` and default to empty.
or `removeFilters` to remove from defaults.
Compiler parameters should be passed as `options=-O2` and default to empty.
The text request is designed for simplicity for command-line clients like `curl` The text request is designed for simplicity for command-line clients like `curl`
@@ -207,8 +198,7 @@ foo():
ret ret
``` ```
If JSON is present in the request's `Accept` header, the compilation results If JSON is present in the request's `Accept` header, the compilation results are of the form:
are of the form:
(_Optional values are marked with a `**`_) (_Optional values are marked with a `**`_)
@@ -250,12 +240,14 @@ If JSON is present in the request's `Accept` header, the compilation results
} }
``` ```
### `POST /api/shortener` - saves given state *forever* to a shortlink and returns the unique id for the link ### `POST /api/shortener` - saves given state _forever_ to a shortlink and returns the unique id for the link
The body of this post should be in the format of a [ClientState](https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/clientstate.js) The body of this post should be in the format of a
Be sure that the Content-Type of your post is application/json [ClientState](https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/clientstate.js) Be sure that the
Content-Type of your post is application/json
An example of one the easiest forms of a clientstate: An example of one the easiest forms of a clientstate:
```JSON ```JSON
{ {
"sessions": [ "sessions": [
@@ -286,6 +278,7 @@ An example of one the easiest forms of a clientstate:
``` ```
Returns: Returns:
```JSON ```JSON
{ {
"url": "https://godbolt.org/z/Km_340" "url": "https://godbolt.org/z/Km_340"
@@ -298,27 +291,27 @@ The storedId can be used in the api call /api/shortlinkinfo/<id> and to open in
This call opens the website in a state that was previously saved using the built-in shortener. This call opens the website in a state that was previously saved using the built-in shortener.
### `GET /z/<id>/code/<sourceid>` - Returns just the sourcecode from a shortlink ### `GET /z/<id>/code/<sourceid>` - Returns just the sourcecode from a shortlink
This call returns plain/text for the code that was previously saved using the built-in shortener. This call returns plain/text for the code that was previously saved using the built-in shortener.
If there were multiple editors during the saved session, you can retrieve them by setting <sourceid> to 1, 2, 3, etcetera, otherwise <sourceid> can be set to 1. If there were multiple editors during the saved session, you can retrieve them by setting <sourceid> to 1, 2, 3,
etcetera, otherwise <sourceid> can be set to 1.
### `GET /clientstate/<base64>` - Opens the website in a given state ### `GET /clientstate/<base64>` - Opens the website in a given state
This call is to open the website with a given state (without having to store the state first with /api/shortener) This call is to open the website with a given state (without having to store the state first with /api/shortener)
Instead of sending the ClientState JSON in the post body, it will have to be encoded with base64 and attached directly onto the URL. Instead of sending the ClientState JSON in the post body, it will have to be encoded with base64 and attached directly
onto the URL.
# Implementations # Implementations
Here are some examples of projects using the Compiler Explorer API: Here are some examples of projects using the Compiler Explorer API:
* [Commandline CE by ethanhs](https://github.com/ethanhs/cce) (Rust)
* [VIM plugin by ldrumm](https://github.com/ldrumm/compiler-explorer.vim) - [Commandline CE by ethanhs](https://github.com/ethanhs/cce) (Rust)
* [API in Delphi by partouf](https://github.com/partouf/compilerexplorer-api) (Delphi) - [VIM plugin by ldrumm](https://github.com/ldrumm/compiler-explorer.vim)
* [QTCreator Plugin by dobokirisame](https://github.com/dobokirisame/CompilerExplorer) (C++) - [API in Delphi by partouf](https://github.com/partouf/compilerexplorer-api) (Delphi)
* [CLion plugin by ogrebenyuk](https://github.com/ogrebenyuk/compilerexplorer) (Java) - [QTCreator Plugin by dobokirisame](https://github.com/dobokirisame/CompilerExplorer) (C++)
* [QCompilerExplorer - frontend in Qt](https://github.com/Waqar144/QCompilerExplorer) (C++) - [CLion plugin by ogrebenyuk](https://github.com/ogrebenyuk/compilerexplorer) (Java)
* [Emacs client - compiler-explorer.el](https://github.com/mkcms/compiler-explorer.el) - [QCompilerExplorer - frontend in Qt](https://github.com/Waqar144/QCompilerExplorer) (C++)
- [Emacs client - compiler-explorer.el](https://github.com/mkcms/compiler-explorer.el)

View File

@@ -4,45 +4,53 @@
Libraries are hard. Libraries can be needed for user code, but also to run compilers. Libraries are hard. Libraries can be needed for user code, but also to run compilers.
For CE we use a lot of different compilers and environments that need to be separated from the OS's installation, and that makes things more complicated than just building with your standard OS's compiler. For CE we use a lot of different compilers and environments that need to be separated from the OS's installation, and
that makes things more complicated than just building with your standard OS's compiler.
Including header files or equivalent is usually the easy part. If there are binaries involved, things get complicated. Including header files or equivalent is usually the easy part. If there are binaries involved, things get complicated.
We have a couple of separate stages where we use and mix different techniques to be able to produce the right assembly or executables. We have a couple of separate stages where we use and mix different techniques to be able to produce the right assembly
or executables.
* Compilation without linking
* The `LD_LIBRARY_PATH` environment variable is used here to enable the compiler to find the `.so` files that they need to run.
* If you're running a local installation, this is usually your own systems' `LD_LIBRARY_PATH` plus extra things that CE adds through properties.
* On godbolt.org we always start with an empty `LD_LIBRARY_PATH` and add what is set in the properties.
* Building an executable or binary
* We use `-Wl,-rpath=` (or equivalent `rpathFlag`) to force library paths into the executable so that they will always find the same `.so` files no matter where they are run. Usually this also includes lib64 and lib folders that the compiler offers for standard libraries that the toolchain offers.
* Library paths supplied through `-Wl,-rpath=` for shared libraries will be able to dynamically link to the right architecture's `.so` even if multiple paths are given that contain the same `.so` file.
* We use `-L` (or equivalent `libpathFlag`) to enable the compiler to find both static (`.a`) and shared (`.so`) libraries.
* We always add '.' as a path as well because that's where we put libraries that are downloaded from our Conan server.
* We use `-l` (or equivalent `linkFlag`) to say we want to statically or dynamically link to a named library binary (the compiler and linker decide if it's gonna be static or dynamic).
* Running the executable
* We use `LD_LIBRARY_PATH` just in case these are dependencies inherited from the compiler - and for the libraries that are used (also just in case).
- Compilation without linking
- The `LD_LIBRARY_PATH` environment variable is used here to enable the compiler to find the `.so` files that they
need to run.
- If you're running a local installation, this is usually your own systems' `LD_LIBRARY_PATH` plus extra things that
CE adds through properties.
- On godbolt.org we always start with an empty `LD_LIBRARY_PATH` and add what is set in the properties.
- Building an executable or binary
- We use `-Wl,-rpath=` (or equivalent `rpathFlag`) to force library paths into the executable so that they will always
find the same `.so` files no matter where they are run. Usually this also includes lib64 and lib folders that the
compiler offers for standard libraries that the toolchain offers.
- Library paths supplied through `-Wl,-rpath=` for shared libraries will be able to dynamically link to the right
architecture's `.so` even if multiple paths are given that contain the same `.so` file.
- We use `-L` (or equivalent `libpathFlag`) to enable the compiler to find both static (`.a`) and shared (`.so`)
libraries.
- We always add '.' as a path as well because that's where we put libraries that are downloaded from our Conan server.
- We use `-l` (or equivalent `linkFlag`) to say we want to statically or dynamically link to a named library binary
(the compiler and linker decide if it's gonna be static or dynamic).
- Running the executable
- We use `LD_LIBRARY_PATH` just in case these are dependencies inherited from the compiler - and for the libraries
that are used (also just in case).
## Specific properties that are used in certain situations ## Specific properties that are used in certain situations
* Compiler .ldPath - Compiler .ldPath
* is used for `LD_LIBRARY_PATH` to support running the compiler - is used for `LD_LIBRARY_PATH` to support running the compiler
* is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries - is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries
* is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files - is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files
* Compiler .libPath - Compiler .libPath
* is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries - is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries
* is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files - is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files
* Library .libPath - Library .libPath
* is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries - is used for linking (`-Wl,-rpath=` and/or `-L`) during building binaries
* is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files (just in case) - is used for `LD_LIBRARY_PATH` to enable the users's executable to find `.so` files (just in case)
## Example ## Example
Say we have the following things in a `c++.local.properties` file: Say we have the following things in a `c++.local.properties` file:
``` ```INI
compilers=mycl compilers=mycl
compiler.mycl.exe=/home/ubuntu/mycl/bin compiler.mycl.exe=/home/ubuntu/mycl/bin
compiler.mycl.ldPath=/home/ubuntu/mycl/lib/lib64 compiler.mycl.ldPath=/home/ubuntu/mycl/lib/lib64
@@ -57,24 +65,25 @@ libs.mylib.libpath=/home/ubuntu/mylib/lib
libs.mylib.staticliblink=mylib libs.mylib.staticliblink=mylib
``` ```
This will result in the following situations if we want to compile some code with both the mycl compiler and the mylib library: This will result in the following situations if we want to compile some code with both the mycl compiler and the mylib
library:
* Compilation without linking - Compilation without linking
* `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64` - `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64`
* `-I/home/ubuntu/mylib/include` is added to the compilation arguments - `-I/home/ubuntu/mylib/include` is added to the compilation arguments
* Building an executable or binary - Building an executable or binary
* `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64` - `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64`
* The following are added to the compilation arguments - The following are added to the compilation arguments
* `-I/home/ubuntu/mylib/include` (library include path) - `-I/home/ubuntu/mylib/include` (library include path)
* `-Wl,-rpath=/home/ubuntu/mycl/lib/lib64` (compiler library paths) - `-Wl,-rpath=/home/ubuntu/mycl/lib/lib64` (compiler library paths)
* `-Wl,-rpath=/home/ubuntu/mycl/lib/lib32` - `-Wl,-rpath=/home/ubuntu/mycl/lib/lib32`
* `-Wl,-rpath=.` (conan library path) - `-Wl,-rpath=.` (conan library path)
* `-L.` - `-L.`
* `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib` (gcc toolchain library paths) - `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib` (gcc toolchain library paths)
* `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib32` - `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib32`
* `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib64` - `-Wl,-rpath=/home/ubuntu/gcc10/lib/lib64`
* `-Wl,-rpath=/home/ubuntu/mylib/lib` (mylib library path - just in case there are `.so` files used) - `-Wl,-rpath=/home/ubuntu/mylib/lib` (mylib library path - just in case there are `.so` files used)
* `-L/home/ubuntu/mylib/lib` (mylib library path used to find `libmylib.a`) - `-L/home/ubuntu/mylib/lib` (mylib library path used to find `libmylib.a`)
* `-lmylib` (mylib library name) - `-lmylib` (mylib library name)
* Running the executable - Running the executable
* `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64:/home/ubuntu/mycl/lib/lib32:/home/ubuntu/mylib/lib` - `LD_LIBRARY_PATH` is set to `/home/ubuntu/mycl/lib/lib64:/home/ubuntu/mycl/lib/lib32:/home/ubuntu/mylib/lib`

View File

@@ -1,51 +1,52 @@
# Adding a new compiler # Adding a new compiler
This document explains how to add a new compiler to Compiler Explorer ("CE" from here on), first for a local instance, and This document explains how to add a new compiler to Compiler Explorer ("CE" from here on), first for a local instance,
then how to submit PRs to get it into the main CE site. and then how to submit PRs to get it into the main CE site.
## Configuration ## Configuration
Compiler configuration is done through the `etc/config/c++.*.properties` files Compiler configuration is done through the `etc/config/c++.*.properties` files (for C++, other languages follow the
(for C++, other languages follow the obvious pattern, replace as needed for your case). obvious pattern, replace as needed for your case).
The various named configuration files are used in different contexts: for example `etc/config/c++.local.properties` take priority over The various named configuration files are used in different contexts: for example `etc/config/c++.local.properties` take
`etc/config/c++.defaults.properties`. The `local` version is ignored by git, so you can make your own personalised changes there. priority over `etc/config/c++.defaults.properties`. The `local` version is ignored by git, so you can make your own
The live site uses the `etc/config/c++.amazon.properties` file. personalised changes there. The live site uses the `etc/config/c++.amazon.properties` file.
Within the file, configuration is a set of key and value pairs, separated by an `=`. Whitespace is _not_ trimmed. Within the file, configuration is a set of key and value pairs, separated by an `=`. Whitespace is _not_ trimmed. Lines
Lines starting with `#` are considered comments and not parsed. starting with `#` are considered comments and not parsed. The list of compilers is set by the `compilers` key and is a
The list of compilers is set by the `compilers` key and is a list of compiler identifiers or groups, separated by colons. Group names list of compiler identifiers or groups, separated by colons. Group names have an `&` prepended. As a nod to backwards
have an `&` prepended. As a nod to backwards compatibility with very old configurations, a path to a compiler can also be put compatibility with very old configurations, a path to a compiler can also be put in the list, but that doesn't let you
in the list, but that doesn't let you configure many aspects of the compiler, nor does it allow paths with colons in them (since these configure many aspects of the compiler, nor does it allow paths with colons in them (since these are used as
are used as separators). The identifier itself is not important, but must be unique to that compiler. separators). The identifier itself is not important, but must be unique to that compiler.
An example configuration: An example configuration:
``` ```INI
compilers=gcc620:gcc720:&clang compilers=gcc620:gcc720:&clang
``` ```
This says there are two compilers with identifiers `gcc620` and `gcc720`, and a group of compilers called `clang`. For the This says there are two compilers with identifiers `gcc620` and `gcc720`, and a group of compilers called `clang`. For
compilers, CE will look for some keys named `compiler.ID.name` and `compiler.ID.exe` (and some others, detailed later). The `ID` the compilers, CE will look for some keys named `compiler.ID.name` and `compiler.ID.exe` (and some others, detailed
is the identifier of the compiler being looked up. The `name` value is used as the human-readable compiler name shown to users, later). The `ID` is the identifier of the compiler being looked up. The `name` value is used as the human-readable
and the `exe` should be the path name of the compiler executable. compiler name shown to users, and the `exe` should be the path name of the compiler executable.
For example: For example:
``` ```INI
compiler.gcc620.name=GCC 6.2.0 compiler.gcc620.name=GCC 6.2.0
compiler.gcc620.exe=/usr/bin/gcc-6.2.0 compiler.gcc620.exe=/usr/bin/gcc-6.2.0
compiler.gcc720.name=GCC 7.2.0 compiler.gcc720.name=GCC 7.2.0
compiler.gcc720.exe=/usr/bin/gcc-7.2.0 compiler.gcc720.exe=/usr/bin/gcc-7.2.0
``` ```
In addition to the `name` and `exe` per-compiler configuration keys, there are also some other options. Most of them default In addition to the `name` and `exe` per-compiler configuration keys, there are also some other options. Most of them
to sensible values for GCC-like compilers. default to sensible values for GCC-like compilers.
A group is defined similar to a list of compilers, and may contain other groups. Keys for groups start with `group.ID`. A group is defined similar to a list of compilers, and may contain other groups. Keys for groups start with `group.ID`.
Configuration keys applied to the group apply to all compilers in that group (unless overridden by the compiler itself). An example: Configuration keys applied to the group apply to all compilers in that group (unless overridden by the compiler itself).
An example:
``` ```INI
group.clang.compilers=clang4:clang5 group.clang.compilers=clang4:clang5
group.clang.intelAsm=-mllvm -x86-asm-syntax=intel group.clang.intelAsm=-mllvm -x86-asm-syntax=intel
compiler.clang4.name=Clang 4 compiler.clang4.name=Clang 4
@@ -56,12 +57,13 @@ compiler.clang5.exe=/usr/bin/clang5
Note about configuration files hierarchy: Note about configuration files hierarchy:
As mentioned previously, the live site uses `etc/config/c++.amazon.properties` to load its configuration from, As mentioned previously, the live site uses `etc/config/c++.amazon.properties` to load its configuration from, but for
but for properties not defined in the `amazon` file, the values present in `etc/config/c++.defaults.properties` will be used. properties not defined in the `amazon` file, the values present in `etc/config/c++.defaults.properties` will be used.
By design, this does not however work for groups (Nor any other nested property). By design, this does not however work for groups (Nor any other nested property). That is, if in
That is, if in `etc/config/c++.defaults.properties` you define the `intelAsm` property as: `etc/config/c++.defaults.properties` you define the `intelAsm` property as:
```
```INI
versionFlag=--version versionFlag=--version
compilers=&clang compilers=&clang
group.clang.intelAsm=-mllvm -x86-asm-syntax=intel group.clang.intelAsm=-mllvm -x86-asm-syntax=intel
@@ -70,88 +72,91 @@ group.clang.groupName=Clang
``` ```
but `etc/config/c++.amazon.properties` only has: but `etc/config/c++.amazon.properties` only has:
```
```INI
compilers=&clang compilers=&clang
group.clang.groupName=Clang group.clang.groupName=Clang
... ...
``` ```
once the site runs on the Amazon environment, the `&clang` group **will not** have the `intelAsm` property set,
but `versionFlag` will. once the site runs on the Amazon environment, the `&clang` group **will not** have the `intelAsm` property set, but
`versionFlag` will.
### Configuration keys ### Configuration keys
Key Name | Type | Description| | Key Name | Type | Description |
---------|-------|-----| | ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------- |
name | String | Human readable name of the compiler|| | name | String | Human readable name of the compiler |
exe | Path | Path to the executable| | exe | Path | Path to the executable |
alias | Identifier | Another identifier for this compiler (mostly deprecated, used for backwards compatibility with very old CE URLs) | | alias | Identifier | Another identifier for this compiler (mostly deprecated, used for backwards compatibility with very old CE URLs) |
options | String | Additional compiler options passed to the compiler when running it | | options | String | Additional compiler options passed to the compiler when running it |
intelAsm | String | Flags used to select intel assembly format (if not detected automatically)| | intelAsm | String | Flags used to select intel assembly format (if not detected automatically) |
needsMulti | Boolean | Whether the compiler needs multi arch support (defaults to yes if the host has multiarch enabled)| | needsMulti | Boolean | Whether the compiler needs multi arch support (defaults to yes if the host has multiarch enabled) |
supportsBinary | Boolean | Whether this compiler supports compiling to binary| | supportsBinary | Boolean | Whether this compiler supports compiling to binary |
supportsExecute | Boolean | Whether binary output from this compiler can be executed| | supportsExecute | Boolean | Whether binary output from this compiler can be executed |
versionFlag | String | The flag to pass to the compiler to make it emit its version| | versionFlag | String | The flag to pass to the compiler to make it emit its version |
versionRe | RegExp | A regular expression used to capture the version from the version output| | versionRe | RegExp | A regular expression used to capture the version from the version output |
compilerType | String | The name of the class handling this compiler| | compilerType | String | The name of the class handling this compiler |
interpreted | Boolean | Whether this is an interpreted language, and so the "compiler" is really an interpreter| | interpreted | Boolean | Whether this is an interpreted language, and so the "compiler" is really an interpreter |
executionWrapper | Path | Path to script that can execute the compiler's output (e.g. could run under `qemu` or `mpi_run` or similar)| | executionWrapper | Path | Path to script that can execute the compiler's output (e.g. could run under `qemu` or `mpi_run` or similar) |
The `compilerType` option is special: it refers to the Javascript class in `lib/compilers/*.js` which handles running and handling The `compilerType` option is special: it refers to the Javascript class in `lib/compilers/*.js` which handles running
output for this compiler type. and handling output for this compiler type.
## Adding a new compiler locally ## Adding a new compiler locally
It should be pretty straightforward to add a compiler of your own. Create a `etc/config/c++.local.properties` file and override the It should be pretty straightforward to add a compiler of your own. Create a `etc/config/c++.local.properties` file and
`compilers` list to include your own compiler, and its configuration. override the `compilers` list to include your own compiler, and its configuration.
Once you've done that, running `make` should pick up the configuration and during startup you should see your compiler being run Once you've done that, running `make` should pick up the configuration and during startup you should see your compiler
and its version being extracted. If you don't, check for any errors, and try running with `make EXTRA_ARGS='--debug'` to see (a lot of) being run and its version being extracted. If you don't, check for any errors, and try running with
debug output. `make EXTRA_ARGS='--debug'` to see (a lot of) debug output.
If you're looking to add other language compilers for another language, obviously create the `etc/config/LANG.local.properties` in If you're looking to add other language compilers for another language, obviously create the
the above steps, and run with `make EXTRA_ARGS='--language LANG'` (e.g. `etc/config/rust.local.properties` and `etc/config/LANG.local.properties` in the above steps, and run with `make EXTRA_ARGS='--language LANG'` (e.g.
`make EXTRA_ARGS='--language Rust'`). `etc/config/rust.local.properties` and `make EXTRA_ARGS='--language Rust'`).
Test locally, and for many compilers that's probably all you need to do. Some compilers might need a few options tweaks (like Test locally, and for many compilers that's probably all you need to do. Some compilers might need a few options tweaks
the intel asm setting, or the version flag). For a completely new compiler, you might need to define a whole new `compilerType`. (like the intel asm setting, or the version flag). For a completely new compiler, you might need to define a whole new
Doing so is beyond this document's scope at present, but take a look inside `lib/compilers/` to get some idea what might need `compilerType`. Doing so is beyond this document's scope at present, but take a look inside `lib/compilers/` to get some
to be done. idea what might need to be done.
## Adding a new compiler running remotely to your locally built compiler explorer ## Adding a new compiler running remotely to your locally built compiler explorer
If you would like to have both gcc and MSVC running in the "same" compiler explorer, one option would be running gcc on your local If you would like to have both gcc and MSVC running in the "same" compiler explorer, one option would be running gcc on
Linux machine and add a proxy to the MSVC compiler, which is running on a remote Window host. To achieve this, you could your local Linux machine and add a proxy to the MSVC compiler, which is running on a remote Window host. To achieve
this, you could
* Setup compiler explorer on your Linux host as usual - Setup compiler explorer on your Linux host as usual
* Follow [this guide](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsNative.md) - Follow [this guide](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsNative.md) to set up
to set up another compiler explorer instance on your Windows host another compiler explorer instance on your Windows host
* Add your Windows compiler explorer as a proxy to your Linux compiler explorer. You can simply modify your - Add your Windows compiler explorer as a proxy to your Linux compiler explorer. You can simply modify your
`etc/config/c++.local.properties` on your Linux host `etc/config/c++.local.properties` on your Linux host
``` ```
compilers=&gcc:&clang:myWindowsHost@10240 compilers=&gcc:&clang:myWindowsHost@10240
``` ```
Yes it is the `@` symbol rather than the `:` before the port number. Restart the Linux compiler explorer, and you will be able to Yes it is the `@` symbol rather than the `:` before the port number. Restart the Linux compiler explorer, and you will
see the MSVC compiler in the compiler list. be able to see the MSVC compiler in the compiler list.
## Adding a new compiler to the live site ## Adding a new compiler to the live site
On the main CE website, compilers are installed into a `/opt/compiler-explorer/` directory by a set of scripts in the sister On the main CE website, compilers are installed into a `/opt/compiler-explorer/` directory by a set of scripts in the
GitHub repo: https://github.com/compiler-explorer/infra sister GitHub repo: https://github.com/compiler-explorer/infra
In the `update_compilers` directory in that repository are a set of scripts that download and install binaries and compilers. In the `update_compilers` directory in that repository are a set of scripts that download and install binaries and
If you wish to test locally, and can create a `/opt/compiler-explorer` directory on your machine which is readable and writable by your compilers. If you wish to test locally, and can create a `/opt/compiler-explorer` directory on your machine which is
current user, then you can run the scripts directly. The binaries and the free compilers can be installed - the commercial compilers readable and writable by your current user, then you can run the scripts directly. The binaries and the free compilers
live in the `install_nonfree_compilers.sh` and won't work. can be installed - the commercial compilers live in the `install_nonfree_compilers.sh` and won't work.
If your compiler fits nicely into the harness then it should be straightforward to add it there. Anything more complex: contact the CE If your compiler fits nicely into the harness then it should be straightforward to add it there. Anything more complex:
authors for more help. contact the CE authors for more help.
## Putting it all together ## Putting it all together
Hopefully that's enough to get an idea. The ideal case of a GCC-like compiler should be a pull request to add a couple of Hopefully that's enough to get an idea. The ideal case of a GCC-like compiler should be a pull request to add a couple
lines to the `infra` repository to install the compiler, and a pull request to add a few lines to the `LANG.amazon.properties` of lines to the `infra` repository to install the compiler, and a pull request to add a few lines to the
file in this repository. `LANG.amazon.properties` file in this repository.
If you feel like we could improve this document in any way, please contact us. We'd love to hear from you! If you feel like we could improve this document in any way, please contact us. We'd love to hear from you!

View File

@@ -1,25 +1,30 @@
# Adding a new formatter # Adding a new formatter
* Add a `etc/config/compiler-explorer.local.properties` file - Add a `etc/config/compiler-explorer.local.properties` file
- Add a new formatter under the `formatters` key - Add a new formatter under the `formatters` key
- The new formatter can have the following keys: name, exe, styles, type, explicitVersion (to override version - The new formatter can have the following keys: name, exe, styles, type, explicitVersion (to override version
parsing), version (argument to get version info), versionRe (regex to filter out the right version info) parsing), version (argument to get version info), versionRe (regex to filter out the right version info)
- Add a `lib/formatters/<formatter>.js` file using the template below, replacing `Type` and `type` as - Add a `lib/formatters/<formatter>.js` file using the template below, replacing `Type` and `type` as appropriate
appropriate
```js ```js
import { BaseFormatter } from '../base-formatter'; import {BaseFormatter} from '../base-formatter';
export class TypeFormatter extends BaseFormatter { export class TypeFormatter extends BaseFormatter {
static get key() { return 'type'; } static get key() {
return 'type';
}
} }
``` ```
- The value returned by `key` above corresponds to the `type` property you set in the compiler-explorer properties - The value returned by `key` above corresponds to the `type` property you set in the compiler-explorer properties
configuration file. configuration file.
- Tweak `format(source, options)` and `isValidStyle(style)` as necessary. See the JSDoc for `format` and the - Tweak `format(source, options)` and `isValidStyle(style)` as necessary. See the JSDoc for `format` and the
implementations for other formatters to get a further understanding of how to implement `format(source, options)`. implementations for other formatters to get a further understanding of how to implement `format(source, options)`.
* Add your `TypeFormatter` to `lib/formatters/_all.js` in alphabetical order
* You can check the output of http://localhost:10240/api/formats to be sure your formatter is there. - Add your `TypeFormatter` to `lib/formatters/_all.js` in alphabetical order
* Make an installer in the [infra](https://github.com/compiler-explorer/infra) repository. An example patch for adding - You can check the output of http://localhost:10240/api/formats to be sure your formatter is there.
- Make an installer in the [infra](https://github.com/compiler-explorer/infra) repository. An example patch for adding
an installer can be found [here](https://github.com/compiler-explorer/infra/pull/560) an installer can be found [here](https://github.com/compiler-explorer/infra/pull/560)

View File

@@ -2,8 +2,10 @@
If you want to add a new language to the site, you should follow this steps: If you want to add a new language to the site, you should follow this steps:
* Add the new language to the exported `languages` variable in `lib/languages.js`: - Add the new language to the exported `languages` variable in `lib/languages.js`:
- The syntax is as follows:
- The syntax is as follows:
```js ```js
'language-key': { 'language-key': {
name: YOUR_LANGUAGE_DISPLAY_NAME, name: YOUR_LANGUAGE_DISPLAY_NAME,
@@ -12,61 +14,68 @@ If you want to add a new language to the site, you should follow this steps:
alias: [], // Leave empty unless needed alias: [], // Leave empty unless needed
} }
``` ```
- If the language is supported by Monaco Editor (You can find the
list [here](https://github.com/microsoft/monaco-editor/tree/main/src/basic-languages)), you should add it to the list of
languages inside the `MonacoEditorWebpackPlugin` config in `webpack.config.js`
- If not, you should implement your own language mode; see `static/modes/asm-mode.js` as an example. Don't forget
to *require* your mode file in `static/modes/_all.ts`, in alphabetical order
- `language-key` is how your language will be referred internally by the code. In the rest of this document,
replace `{language-key}` by the corresponding value in the real files.
* Add a `lib/compilers/{language-key}.js` file using the template below: - If the language is supported by Monaco Editor (You can find the list
```js [here](https://github.com/microsoft/monaco-editor/tree/main/src/basic-languages)), you should add it to the list of
import { BaseCompiler } from '../base-compiler'; languages inside the `MonacoEditorWebpackPlugin` config in `webpack.config.js`
- If not, you should implement your own language mode; see `static/modes/asm-mode.js` as an example. Don't forget to
_require_ your mode file in `static/modes/_all.ts`, in alphabetical order
- `language-key` is how your language will be referred internally by the code. In the rest of this document, replace
`{language-key}` by the corresponding value in the real files.
export class LanguageCompiler extends BaseCompiler { - Add a `lib/compilers/{language-key}.js` file using the template below:
static get key() { return 'language'; }
```js
import {BaseCompiler} from '../base-compiler';
export class LanguageCompiler extends BaseCompiler {
static get key() {
return 'language';
} }
``` }
- The value returned by `key` above corresponds to the `compilerType` value ```
in `etc/config/{language-key}.defaults.properties` (Explained below). This is usually `{language-key}`, but you
can use whatever fits best
- Override the `OptionsForFilter` method from the base class
- Comment out the line saying `fs.remove(result.dirPath);` in base-compiler.js, so the latest CE compile attempt
remains on disk for you to review
- Remember to undo this change before opening a PR!
- For reference, the basic behaviour of BaseCompiler is:
- make a random temporary folder
- save example.extension to the new folder, the full path to this is the `inputFilename`
- the `outputFilename` is determined by the `getOutputFilename()` method
- execute the compiler.exe with the arguments from `OptionsForFilter()` and adding `inputFilename`
- be aware that the language class is only instanced once, so storing state is not possible
- If the compiler has problems with the defaults, you will have to override the `runCompiler()` method too. When
overriding it, here are some ideas
- set `execOptions.customCwd` parameter if the working directory needs to be somewhere else
- set `execOptions.env` parameter if the compiler requires special environment variables
- manipulate `options`, but make sure the user can still add their own arguments in CE
* Add your `LanguageCompiler` to `lib/compilers/_all.js`, in alphabetical order - The value returned by `key` above corresponds to the `compilerType` value in
`etc/config/{language-key}.defaults.properties` (Explained below). This is usually `{language-key}`, but you can use
whatever fits best
- Override the `OptionsForFilter` method from the base class
- Comment out the line saying `fs.remove(result.dirPath);` in base-compiler.js, so the latest CE compile attempt
remains on disk for you to review
- Remember to undo this change before opening a PR!
- For reference, the basic behaviour of BaseCompiler is:
- make a random temporary folder
- save example.extension to the new folder, the full path to this is the `inputFilename`
- the `outputFilename` is determined by the `getOutputFilename()` method
- execute the compiler.exe with the arguments from `OptionsForFilter()` and adding `inputFilename`
- be aware that the language class is only instanced once, so storing state is not possible
- If the compiler has problems with the defaults, you will have to override the `runCompiler()` method too. When
overriding it, here are some ideas
- set `execOptions.customCwd` parameter if the working directory needs to be somewhere else
- set `execOptions.env` parameter if the compiler requires special environment variables
- manipulate `options`, but make sure the user can still add their own arguments in CE
* Add a `etc/config/{language-key}.local.properties` file: - Add your `LanguageCompiler` to `lib/compilers/_all.js`, in alphabetical order
- The syntax for its basic contents is documented in [AddingACompiler.md](AddingACompiler.md)
- This file is ignored by Git, so that you can test the config locally
- You should add 1 compiler for the language you want to test
- Test the command line options of the language compilers outside CE
* Add a new file `etc/config/{language-key}.defaults.properties`. This is where a default configuration will live. - Add a `etc/config/{language-key}.local.properties` file:
- Usually, this loads default compilers from their usual paths on a normal installation
(Check `etc/config/c++.defaults.properties` for an example)
* Of important note, for both files, is to properly define `compilerType` property in the newly added compilers. This - The syntax for its basic contents is documented in [AddingACompiler.md](AddingACompiler.md)
- This file is ignored by Git, so that you can test the config locally
- You should add 1 compiler for the language you want to test
- Test the command line options of the language compilers outside CE
- Add a new file `etc/config/{language-key}.defaults.properties`. This is where a default configuration will live.
- Usually, this loads default compilers from their usual paths on a normal installation (Check
`etc/config/c++.defaults.properties` for an example)
- Of important note, for both files, is to properly define `compilerType` property in the newly added compilers. This
should equal the value returned by your `LanguageCompiler.key` function should equal the value returned by your `LanguageCompiler.key` function
* Running `make dev EXTRA_ARGS="--debug --language {language-key}"` to tell CE to only load your new language - Running `make dev EXTRA_ARGS="--debug --language {language-key}"` to tell CE to only load your new language
* You can check http://127.0.0.1:10240/api/compilers to be sure your language and compilers are there - You can check http://127.0.0.1:10240/api/compilers to be sure your language and compilers are there
* Make an installer in the [infra](https://github.com/compiler-explorer/infra) repository - Make an installer in the [infra](https://github.com/compiler-explorer/infra) repository
* Add your language files (`{language-key}.*.properties` and `lib/compilers/{language-key}.js`) to the list - Add your language files (`{language-key}.*.properties` and `lib/compilers/{language-key}.js`) to the list in
in `.github/labeler.yml` `.github/labeler.yml`

View File

@@ -1,42 +1,41 @@
# Adding a new library # Adding a new library
This document explains how to add a new library to Compiler Explorer ("CE" from here on), first for a local instance, and This document explains how to add a new library to Compiler Explorer ("CE" from here on), first for a local instance,
then how to submit PRs to get it into the main CE site. and then how to submit PRs to get it into the main CE site.
Note that most libraries are Header-only. This is the easiest form of library to support. If the library needs to be built, Note that most libraries are Header-only. This is the easiest form of library to support. If the library needs to be
there are some caveats, best practices and good to knows. Consult the bottom of this page for details. built, there are some caveats, best practices and good to knows. Consult the bottom of this page for details.
## Configuration ## Configuration
Library configurations are part of the compiler's properties, which is done through the `etc/config/c++.*.properties` files Library configurations are part of the compiler's properties, which is done through the `etc/config/c++.*.properties`
(for C++, other languages follow the obvious pattern). The various named configuration files are used in different contexts: files (for C++, other languages follow the obvious pattern). The various named configuration files are used in different
for example `etc/config/c++.local.properties` take priority over `etc/config/c++.defaults.properties`. contexts: for example `etc/config/c++.local.properties` take priority over `etc/config/c++.defaults.properties`. The
The `local` version is ignored by git, so you can make your own personalised changes there. `local` version is ignored by git, so you can make your own personalised changes there. The live site uses the
The live site uses the `etc/config/c++.amazon.properties` file. `etc/config/c++.amazon.properties` file.
Within the file, configuration is a set of key and value pairs, separated by an `=`. Whitespace is _not_ trimmed. Within the file, configuration is a set of key and value pairs, separated by an `=`. Whitespace is _not_ trimmed. Lines
Lines starting with `#` are considered comments and not parsed. starting with `#` are considered comments and not parsed. The list of libraries is set by the `libs` key and is a list
The list of libraries is set by the `libs` key and is a list of library identifiers, separated by colons. of library identifiers, separated by colons. The identifier itself is not important, but must be unique to that library.
The identifier itself is not important, but must be unique to that library.
An example configuration: An example configuration:
``` ```INI
libs=kvasir:boost:rangesv3 libs=kvasir:boost:rangesv3
``` ```
This says there are three libraries with identifiers `kvasir`, `boost` and `rangesv3`. CE will look for the key named This says there are three libraries with identifiers `kvasir`, `boost` and `rangesv3`. CE will look for the key named
`libs.ID.versions`, `libs.ID.name` and the optionals `libs.ID.url` & `libs.ID.description`. The `ID` is the identifier (The one we just set) of the library being looked up. `libs.ID.versions`, `libs.ID.name` and the optionals `libs.ID.url` & `libs.ID.description`. The `ID` is the identifier
The `name` key expects the human-readable name of the library (Note that you can use spaces here!). (The one we just set) of the library being looked up. The `name` key expects the human-readable name of the library
The `versions` key expects another list, akin to the libs key itself. This time, you have to define the available versions (Note that you can use spaces here!). The `versions` key expects another list, akin to the libs key itself. This time,
for each library. you have to define the available versions for each library. The `url` key expects an unescaped url, where users can go
The `url` key expects an unescaped url, where users can go to learn more about the library (This is usually the project's homepage, or in its to learn more about the library (This is usually the project's homepage, or in its absence, the GitHub repo). The
absence, the GitHub repo). `description` key should be use as an extremely short description of the library. Usually used to spell the library's
The `description` key should be use as an extremely short description of the library. Usually used to spell the library's full name in cases where the `name` key is an acronym. full name in cases where the `name` key is an acronym.
For example: For example:
``` ```INI
libs.kvasir.name=Kvasir::mpl libs.kvasir.name=Kvasir::mpl
libs.kvasir.versions=trunk libs.kvasir.versions=trunk
libs.kvasir.url=https://github.com/kvasir-io/Kvasir libs.kvasir.url=https://github.com/kvasir-io/Kvasir
@@ -51,13 +50,14 @@ libs.rangesv3.versions=trunk:0110
libs.rangesv3.url=https://github.com/ericniebler/range-v3 libs.rangesv3.url=https://github.com/ericniebler/range-v3
``` ```
Now, for each declared version, CE will look for a `version` key, a human-readable string representing the corresponding version, Now, for each declared version, CE will look for a `version` key, a human-readable string representing the corresponding
and `path`, a list consisting of the paths separated by colon `:` (or semicolon `;` on Windows) to add to the inclusion path of the library. version, and `path`, a list consisting of the paths separated by colon `:` (or semicolon `;` on Windows) to add to the
Optionally, you can provide a `libpath`, a list consisting of paths to add to your linker path. inclusion path of the library. Optionally, you can provide a `libpath`, a list consisting of paths to add to your linker
path.
This would leave us with: This would leave us with:
``` ```INI
libs.boost.name=Boost libs.boost.name=Boost
libs.boost.versions=175:176 libs.boost.versions=175:176
libs.boost.url=http://www.boost.org/ libs.boost.url=http://www.boost.org/
@@ -90,106 +90,124 @@ libs.rangesv3.versions.0110.version=0.11.0
libs.rangesv3.versions.0110.path=/opt/compiler-explorer/libs/rangesv3/0.11.0/include libs.rangesv3.versions.0110.path=/opt/compiler-explorer/libs/rangesv3/0.11.0/include
``` ```
If you're adding a new library and plan to submit a PR for it, please make sure that its identifier appears in alphabetical order If you're adding a new library and plan to submit a PR for it, please make sure that its identifier appears in
in the `libs` property. You should also put all its related configuration in that same order when defining it. alphabetical order in the `libs` property. You should also put all its related configuration in that same order when
This helps us keep the config manageable until further automation can be implemented. Thank you! defining it. This helps us keep the config manageable until further automation can be implemented. Thank you!
## Setting default libraries ## Setting default libraries
The `defaultLibs` key specifies an array of libs/versions which will be enabled by default when the user visits the site. The `defaultLibs` key specifies an array of libs/versions which will be enabled by default when the user visits the
The expected format is: site. The expected format is:
```
```INI
defaultLibs=libKeyA.version:libKeyB.version:libKeyC.version defaultLibs=libKeyA.version:libKeyB.version:libKeyC.version
``` ```
Where `libKey` is the key of the library to be enabled by default, and `version` is the version key to load.
Note that the site won't complain if invalid key/version pairs are set. Repeating a lib key more than once is supported. Where `libKey` is the key of the library to be enabled by default, and `version` is the version key to load. Note that
the site won't complain if invalid key/version pairs are set. Repeating a lib key more than once is supported.
## Adding a new library locally ## Adding a new library locally
It should be pretty straightforward to add a library of your own. Create a `etc/config/c++.local.properties` file and override the It should be pretty straightforward to add a library of your own. Create a `etc/config/c++.local.properties` file and
`libs` list to include your own library, and its configuration. override the `libs` list to include your own library, and its configuration.
Once you've done that, running `make` should pick up the configuration, and you should be able to use them from the library dropdown Once you've done that, running `make` should pick up the configuration, and you should be able to use them from the
on the compiler view (The book icon) library dropdown on the compiler view (The book icon)
If you're looking to add libraries for another language, obviously create the `etc/config/LANG.local.properties` in If you're looking to add libraries for another language, obviously create the `etc/config/LANG.local.properties` in the
the above steps, and run with `make EXTRA_ARGS='--language LANG` (e.g. `etc/config/rust.local.properties` and above steps, and run with `make EXTRA_ARGS='--language LANG` (e.g. `etc/config/rust.local.properties` and
`make EXTRA_ARGS='--language Rust'`). `make EXTRA_ARGS='--language Rust'`).
Test locally, and for many compilers that's probably all you need to do. Some compilers might need a few options tweaks (like Test locally, and for many compilers that's probably all you need to do. Some compilers might need a few options tweaks
the intel asm setting, or the version flag). For a completely new compiler, you might need to define a whole new `compilerType`. (like the intel asm setting, or the version flag). For a completely new compiler, you might need to define a whole new
Doing so is beyond this document's scope at present, but take a look inside `lib/compilers/` to get some idea what might need `compilerType`. Doing so is beyond this document's scope at present, but take a look inside `lib/compilers/` to get some
to be done. idea what might need to be done.
## Adding a new library to the live site ## Adding a new library to the live site
On the main CE website, libraries are installed into a `/opt/compiler-explorer/` directory by a set of scripts in the sister On the main CE website, libraries are installed into a `/opt/compiler-explorer/` directory by a set of scripts in the
GitHub repo: https://github.com/compiler-explorer/infra sister GitHub repo: https://github.com/compiler-explorer/infra
In the `bin/yaml` directory in that repository are a set of yaml files that configure the download, install and building of the libraries. In the `bin/yaml` directory in that repository are a set of yaml files that configure the download, install and building
If you wish to test locally, and can create a `/opt/compiler-explorer` directory on your machine which is readable and writable by your of the libraries. If you wish to test locally, and can create a `/opt/compiler-explorer` directory on your machine which
current user, then you can run the scripts directly. is readable and writable by your current user, then you can run the scripts directly.
Example of configuring a library that is header only: Example of configuring a library that is header only:
```
sol2: ```yaml
type: github sol2:
method: clone_branch type: github
repo: ThePhD/sol2 method: clone_branch
check_file: include/sol/sol.hpp repo: ThePhD/sol2
build_type: none check_file: include/sol/sol.hpp
targets: build_type: none
- v3.2.1 targets:
- v3.2.1
``` ```
Example of configuring a library that is linked against: Example of configuring a library that is linked against:
```
catch2: ```yaml
type: github catch2:
repo: catchorg/Catch2 type: github
build_type: cmake repo: catchorg/Catch2
make_targets: build_type: cmake
- Catch2 make_targets:
- Catch2WithMain - Catch2
target_prefix: v - Catch2WithMain
targets: target_prefix: v
- 3.0.0-preview2 targets:
- 3.0.0-preview2
``` ```
If your library fits nicely into the harness then it should be straightforward to add it there. Anything more complex: contact the CE If your library fits nicely into the harness then it should be straightforward to add it there. Anything more complex:
authors for more help. contact the CE authors for more help.
Remember to also add the library dependencies following the same steps. It's on you if those should also appear in the UI. Remember to also add the library dependencies following the same steps. It's on you if those should also appear in the
UI.
## Adding compilers with limited library support ## Adding compilers with limited library support
If you have libraries that you don't want to be shown with a compiler, you can limit the libraries per compiler. By default, all libraries are visible for all compilers. If you have libraries that you don't want to be shown with a compiler, you can limit the libraries per compiler. By
default, all libraries are visible for all compilers.
For example if you only want all versions of fmt, and version 0.3.0 of Ranges, you can do the following: For example if you only want all versions of fmt, and version 0.3.0 of Ranges, you can do the following:
```
```ini
compiler.mycompiler.supportedLibraries=fmt:rangesv3.030 compiler.mycompiler.supportedLibraries=fmt:rangesv3.030
``` ```
## Putting it all together ## Putting it all together
Hopefully that's enough to get an idea. The ideal case should be a pull request to add a couple of Hopefully that's enough to get an idea. The ideal case should be a pull request to add a couple of lines to the `infra`
lines to the `infra` repository to install the library, and a pull request to add a few lines to the `LANG.amazon.properties` repository to install the library, and a pull request to add a few lines to the `LANG.amazon.properties` file in this
file in this repository. repository.
If you feel like we could improve this document in any way, please contact us. We'd love to hear from you! If you feel like we could improve this document in any way, please contact us. We'd love to hear from you!
# Adding a library that needs to be compiled to .a or .so binaries # Adding a library that needs to be compiled to .a or .so binaries
Supporting library binaries are a complicated matter. Supporting library binaries are a complicated matter.
For "C" shared libraries is relatively easy, is mostly a "solved problem", and the most common way of connecting software and libraries together. OpenSSL has .so's to link against for x86-64 and x86. However, we currently do not offer any other platforms, and it gets a lot harder if we tried to support that. Not to mention we currently do not have hardware in the cloud for other platforms to actually execute your code. For "C" shared libraries is relatively easy, is mostly a "solved problem", and the most common way of connecting
software and libraries together. OpenSSL has .so's to link against for x86-64 and x86. However, we currently do not
offer any other platforms, and it gets a lot harder if we tried to support that. Not to mention we currently do not have
hardware in the cloud for other platforms to actually execute your code.
For C++ libraries, static or shared, there is no standard or common way of building libraries. To be sure linking will work, we have to rebuild the libraries for every compiler we support. We try to support at least x86-64, x86 and if that's not possible - the default target of the compiler. For all llvm/clang based compilers, we also try to build the libraries for libc++, just to be sure that doesn't give any runtime issues. For C++ libraries, static or shared, there is no standard or common way of building libraries. To be sure linking will
work, we have to rebuild the libraries for every compiler we support. We try to support at least x86-64, x86 and if
that's not possible - the default target of the compiler. For all llvm/clang based compilers, we also try to build the
libraries for libc++, just to be sure that doesn't give any runtime issues.
There are also some specific compiler flags that cause ABI incompatibility, but we're still looking for common cases; if you have any use-cases of flags that causes linking or runtime errors, please let us know. There are also some specific compiler flags that cause ABI incompatibility, but we're still looking for common cases; if
you have any use-cases of flags that causes linking or runtime errors, please let us know.
For us to have the possibility of crosscompiling with multiple compilers, it's recommended to be able to build with CMake. CMake by default has support to provide different flags during compilation. Makefiles can provide ways for doing the same, but often they have variables and flags that cannot be changed. If you're a library developer, please take into account that we will need ways to set at least CC, CXX, CXXFLAGS. Be also aware that we will probably supply -Wl-rpath's and/or -L to ensure that the library knows where to find their dependencies. For us to have the possibility of crosscompiling with multiple compilers, it's recommended to be able to build with
CMake. CMake by default has support to provide different flags during compilation. Makefiles can provide ways for doing
the same, but often they have variables and flags that cannot be changed. If you're a library developer, please take
into account that we will need ways to set at least CC, CXX, CXXFLAGS. Be also aware that we will probably supply
-Wl-rpath's and/or -L to ensure that the library knows where to find their dependencies.
Because of the amount of combinations we need to produce, only the later tagged versions of most libraries have priority in providing builds for. Daily trunk/master versions are out as well, until we figure out a way to efficiently provide builds for this. Because of the amount of combinations we need to produce, only the later tagged versions of most libraries have priority
in providing builds for. Daily trunk/master versions are out as well, until we figure out a way to efficiently provide
builds for this.

View File

@@ -4,7 +4,7 @@ Tools are a way to execute something on your code or the output of a compilation
Adding tools requires adding configuration to a properties file for a specific language: Adding tools requires adding configuration to a properties file for a specific language:
```yaml ```INI
tools=rewritecpp tools=rewritecpp
tools.rewritecpp.name=rewritecpp tools.rewritecpp.name=rewritecpp
@@ -19,25 +19,31 @@ tools.rewritecpp.options=--a
tools.rewritecpp.args=--b tools.rewritecpp.args=--b
``` ```
The `name` and `exe` are what they say they are, this is the display name for within CE and the tool executable that will be used. The `name` and `exe` are what they say they are, this is the display name for within CE and the tool executable that
will be used.
The `type` of the tool represents the stage in which the tool will run: The `type` of the tool represents the stage in which the tool will run:
* independent - when running a tool on sourcecode
* postcompilation - when running a tool on the assembly or a binary
The `exclude` property is to indicate which compilers are proven to be incompatible with the tool. - independent - when running a tool on sourcecode
You can supply the full id of the compiler, or a partial id (for example 'arm' to exclude all arm compilers). - postcompilation - when running a tool on the assembly or a binary
The `class` of the tool says which javascript class is needed to run the tool and process its output. The folder _lib/tooling_ is used for these classes. The `exclude` property is to indicate which compilers are proven to be incompatible with the tool. You can supply the
full id of the compiler, or a partial id (for example 'arm' to exclude all arm compilers).
The `class` of the tool says which javascript class is needed to run the tool and process its output. The folder
_lib/tooling_ is used for these classes.
Should you want to deviate from the standard behaviour of `base-tool`, which runs the tool on the sourcecode filename, Should you want to deviate from the standard behaviour of `base-tool`, which runs the tool on the sourcecode filename,
you should add a new class that extends from `base-tool`. you should add a new class that extends from `base-tool`.
The `stdinHint` is there to show the user a hint as to what the stdin field is used for in the tool. To disable stdin you can use _disabled_ here. The `stdinHint` is there to show the user a hint as to what the stdin field is used for in the tool. To disable stdin
you can use _disabled_ here.
The `monacoStdin` option makes the stdin editor a separate pane containing a monaco editor. This is useful when a tool has complex input spanning multiple lines and it's more friendly to indent it. The `monacoStdin` option makes the stdin editor a separate pane containing a monaco editor. This is useful when a tool
has complex input spanning multiple lines and it's more friendly to indent it.
The `languageId` can be used to highlight the output of the tool according to a language known within CE. For example `cppp` will highlight c++ output. Leaving `languageId` empty will use the terminal-like output. The `languageId` can be used to highlight the output of the tool according to a language known within CE. For example
`cppp` will highlight c++ output. Leaving `languageId` empty will use the terminal-like output.
The `options` field is useful for tools that derive `base-tool` and want to add non-user configurable options to it The `options` field is useful for tools that derive `base-tool` and want to add non-user configurable options to it
@@ -45,7 +51,8 @@ The `args` field is shown and editable by the user in the UI, and passed automat
# compilationInfo # compilationInfo
When writing a special class for a tool, you will probably need the `compilationInfo` parameter to pass the correct parameters to the tool. When writing a special class for a tool, you will probably need the `compilationInfo` parameter to pass the correct
parameters to the tool.
The contents of `compilationInfo` varies slightly between the different `type`s of tools. The contents of `compilationInfo` varies slightly between the different `type`s of tools.
@@ -64,7 +71,8 @@ The contents of `compilationInfo` varies slightly between the different `type`s
} }
``` ```
The `filters` can be used to assert boundary conditions or adjust the tooling process based on the filters the user checked on or off. The `filters` can be used to assert boundary conditions or adjust the tooling process based on the filters the user
checked on or off.
The `inputFilename` contains the path to the sourcecode stored on disk. The `source` contains the sourcecode as text. The `inputFilename` contains the path to the sourcecode stored on disk. The `source` contains the sourcecode as text.
@@ -72,7 +80,6 @@ The `dirPath` can be used to write extra files to disk which the tool might need
The `options` are the arguments the user gave for the compilation. The `options` are the arguments the user gave for the compilation.
## compilationInfo for postcompilation tools ## compilationInfo for postcompilation tools
```json ```json
@@ -97,7 +104,8 @@ The `options` are the arguments the user gave for the compilation.
`code` indicates the exitcode of the compilation. Usually, 0 means everything's ok. `code` indicates the exitcode of the compilation. Usually, 0 means everything's ok.
`asm` contains the returned assembly. This is the same assembly that is shown within compiler-explorer, including extra information like for which sourcecode line the assembly was generated. `asm` contains the returned assembly. This is the same assembly that is shown within compiler-explorer, including extra
information like for which sourcecode line the assembly was generated.
`stderr` and `stdout` contain the different outputs from the compilation process. `stderr` and `stdout` contain the different outputs from the compilation process.

View File

@@ -1,7 +1,7 @@
# Adding Assembly Documentation for a new instruction set # Adding Assembly Documentation for a new instruction set
This document explains how to add assembly documentation for a new instruction set to Compiler Explorer This document explains how to add assembly documentation for a new instruction set to Compiler Explorer ("CE" from here
("CE" from here on). on).
If you were not already aware, CE has both quick-tip and more thorough assembly instruction documentation available for If you were not already aware, CE has both quick-tip and more thorough assembly instruction documentation available for
a couple instruction sets (currently JVM bytecode, amd64 and arm32). The feature is demonstrated in the gif below. a couple instruction sets (currently JVM bytecode, amd64 and arm32). The feature is demonstrated in the gif below.
@@ -12,8 +12,8 @@ To add a new assembly documentation handler, you need to perform the following s
## 1. Find a data source ## 1. Find a data source
First you need to find a data source to get our instruction info from. While it is possible to write down First you need to find a data source to get our instruction info from. While it is possible to write down information
information about every single instruction for an instruction set, it's far from maintainable, and it is a lot of work. about every single instruction for an instruction set, it's far from maintainable, and it is a lot of work.
Existing assembly documentation handlers use some sort of established documentation. The arm32 handler uses the Existing assembly documentation handlers use some sort of established documentation. The arm32 handler uses the
developer.arm.com website and the JVM bytecode handler uses Oracle's documentation. developer.arm.com website and the JVM bytecode handler uses Oracle's documentation.
@@ -29,9 +29,9 @@ How you generate this file is completely up to you, just make sure it's easy for
well. If you need inspiration on how to write this tool, you can look at the `docenizer-*` scripts found in well. If you need inspiration on how to write this tool, you can look at the `docenizer-*` scripts found in
`/etc/scripts/docenizers` in the source control tree. `/etc/scripts/docenizers` in the source control tree.
CE expects the tool to output the file into the `/lib/asm-docs/generated/` folder with a name following the existing CE expects the tool to output the file into the `/lib/asm-docs/generated/` folder with a name following the existing
convention. Each case in the switch should return a piece of formatted HTML to insert into the popup, a tooltip text convention. Each case in the switch should return a piece of formatted HTML to insert into the popup, a tooltip text for
for the on-hover tooltip and a URL to external documentation. the on-hover tooltip and a URL to external documentation.
```js ```js
case "CALL": case "CALL":
@@ -48,28 +48,31 @@ Once your tool has generated the JavaScript file, you want to connect it to CE.
in the `/lib/asm-docs` directory which is adjacent to your newly generated JavaScript file. in the `/lib/asm-docs` directory which is adjacent to your newly generated JavaScript file.
First you want to add a new file named after your instruction set which exports a class extending the First you want to add a new file named after your instruction set which exports a class extending the
`BaseAssemblyDocumentationProvider` class. The class should implement the `getInstructionInformation` method which `BaseAssemblyDocumentationProvider` class. The class should implement the `getInstructionInformation` method which in
in most cases, delegates to your generated JavaScript. Instruction sets like Arm32 have use code to tweak the output most cases, delegates to your generated JavaScript. Instruction sets like Arm32 have use code to tweak the output if
if needed. needed.
This method is expected to take the instruction opcode in full uppercase and either return the associated data or null This method is expected to take the instruction opcode in full uppercase and either return the associated data or null
if not found. if not found.
```ts ```ts
import { getAsmOpcode } from './generated//asm-docs-java'; import {getAsmOpcode} from './generated//asm-docs-java';
import { BaseAssemblyDocumentationProvider } from './base'; import {BaseAssemblyDocumentationProvider} from './base';
export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider { export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider {
// Return the instruction set name // Return the instruction set name
public static get key() { return 'java'; } public static get key() {
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null { return 'java';
return getAsmOpcode(instruction) || null; }
} public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
return getAsmOpcode(instruction) || null;
}
} }
``` ```
Finally we want to tell CE that the new documentation provider exists. This is done by re-exporting the class inside Finally we want to tell CE that the new documentation provider exists. This is done by re-exporting the class inside
`/lib/asm-docs/_all.ts`. Please keep the exports here in alphabetic order. `/lib/asm-docs/_all.ts`. Please keep the exports here in alphabetic order.
## 4. Testing ## 4. Testing
Testing new assembly documentation providers is really easy. It is just a matter of modifying the `TEST_MATRIX` variable Testing new assembly documentation providers is really easy. It is just a matter of modifying the `TEST_MATRIX` variable

View File

@@ -1,23 +1,24 @@
This is an overview of what building and adding a compiler to the site looks like, using GCC as an example, This is an overview of what building and adding a compiler to the site looks like, using GCC as an example, but note
but note that the process is similar for all other types of compilers. that the process is similar for all other types of compilers.
* Build GCC versions with the relevant magic. - Build GCC versions with the relevant magic. We build all our own GCCs using Docker from
We build all our own GCCs using Docker from [this repo](https://github.com/compiler-explorer/gcc-builder) [this repo](https://github.com/compiler-explorer/gcc-builder)
* For non-trunk builds we manually run the docker image. - For non-trunk builds we manually run the docker image. For trunk dailies we have a
For trunk dailies we have a [cron job](https://github.com/compiler-explorer/infra/blob/main/crontab.admin#L8) [cron job](https://github.com/compiler-explorer/infra/blob/main/crontab.admin#L8) that runs a
that runs a [script](https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh) to build them. [script](https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh) to build them.
* Built tarballs are uploaded to S3, - Built tarballs are uploaded to S3, and installed by our
and installed by our [custom tool](https://github.com/compiler-explorer/infra/blob/main/bin/lib/ce_install.py) [custom tool](https://github.com/compiler-explorer/infra/blob/main/bin/lib/ce_install.py) from a
from a [YAML configuration file](https://github.com/compiler-explorer/infra/blob/main/bin/yaml/cpp.yaml) [YAML configuration file](https://github.com/compiler-explorer/infra/blob/main/bin/yaml/cpp.yaml)
* The installation puts compilers on a shared NFS drive at `/opt/compiler-explorer/gcc-some-version/` - The installation puts compilers on a shared NFS drive at `/opt/compiler-explorer/gcc-some-version/`
* We then configure CE to look for the compiler - We then configure CE to look for the compiler
[here](https://github.com/compiler-explorer/compiler-explorer/blob/main/etc/config/c%2B%2B.amazon.properties#L9). [here](https://github.com/compiler-explorer/compiler-explorer/blob/main/etc/config/c%2B%2B.amazon.properties#L9).
* If we need to customise the way we execute the compiler and/or display the results, - If we need to customise the way we execute the compiler and/or display the results, then we can change the
then we can change the "[driver](https://github.com/compiler-explorer/compiler-explorer/tree/main/lib/compilers)" "[driver](https://github.com/compiler-explorer/compiler-explorer/tree/main/lib/compilers)" for the compiler. Usually
for the compiler. Usually we can just override a few aspects of the driver, we can just override a few aspects of the driver, relying on the defaults from the
relying on the defaults from the [base driver](https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/base-compiler.js). [base driver](https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/base-compiler.js).
* Any UI changes are a bit more work. - Any UI changes are a bit more work.
More info still in [Adding a Compiler](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/AddingACompiler.md), More info still in
and if you can bear listening to Matt, here's [a talk](https://www.youtube.com/watch?v=kIoZDUd5DKw) [Adding a Compiler](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/AddingACompiler.md), and if
about some behind the scenes stuff, with [slides online](https://www.youtube.com/watch?v=kIoZDUd5DKw). you can bear listening to Matt, here's [a talk](https://www.youtube.com/watch?v=kIoZDUd5DKw) about some behind the
scenes stuff, with [slides online](https://www.youtube.com/watch?v=kIoZDUd5DKw).

View File

@@ -1,33 +1,53 @@
# Running EWARM compiler on windows host # Running EWARM compiler on windows host
This document will show a little insight on how to get the IAR ARM compiler working with compiler explorer *(Some line highlighting is broken as EWAVR is different from EWARM)*
This document will show a little insight on how to get the IAR ARM compiler working with compiler explorer _(Some line
highlighting is broken as EWAVR is different from EWARM)_
# Prerequisites # Prerequisites
To run the IAR ARM compiler you will need: To run the IAR ARM compiler you will need:
- A valid installation of the IAR ARM compiler. [EWARM](https://www.iar.com/iar-embedded-workbench/#!?architecture=Arm) has a free 30-day trial on their website - A valid installation of the IAR ARM compiler. [EWARM](https://www.iar.com/iar-embedded-workbench/#!?architecture=Arm)
- Technically you need a license as well to run the compiler, however you can get by with the 30-day free trial, as you will be able to run the compiler for 30 days for free has a free 30-day trial on their website
- Technically you need a license as well to run the compiler, however you can get by with the 30-day free trial, as you
will be able to run the compiler for 30 days for free
- MinGW C++ toolchain for `c++filt` and `objdump` - MinGW C++ toolchain for `c++filt` and `objdump`
## IAR ARM Compiler ## IAR ARM Compiler
This compiler will be installed along with the IAR Embedded Workbench (EWARM). Default installation location is under `C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.2\arm\bin\iccarm.exe`
This compiler will be installed along with the IAR Embedded Workbench (EWARM). Default installation location is under
`C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.2\arm\bin\iccarm.exe`
## MinGW C++ Toolchain ## MinGW C++ Toolchain
We need to install this toolchain through [MSYS2](https://www.msys2.org/), as it contains `c++filt` and `objdump`, which are needed to demangle the assembly
We need to install this toolchain through [MSYS2](https://www.msys2.org/), as it contains `c++filt` and `objdump`, which
are needed to demangle the assembly
- First download [MSYS2](https://www.msys2.org/) - First download [MSYS2](https://www.msys2.org/)
- Install it and run it, entering the first command `pacman -Syuu`, this command will update all the internal MSYS2 modules to their latest version. This command will also update all installed modules, such as the toolchain if it was installed. - Install it and run it, entering the first command `pacman -Syuu`, this command will update all the internal MSYS2
- When you run the command for the first time, it will exit the bash console. You have to open it again and run the same command again `pacman -Syuu` modules to their latest version. This command will also update all installed modules, such as the toolchain if it was
- After the second time, everything will be up to date. To install the MinGW toolchain, run `pacman -S mingw-w64-x86_64-toolchain`. This will install the toolchain to your MSYS2 default installation path under `C:\msys64\mingw64\bin` installed.
- Add this path `C:\msys64\mingw64\bin` to windows global `PATH` - When you run the command for the first time, it will exit the bash console. You have to open it again and run the same
- Test by running `c++filt --help` from windows command prompt, if everything is set up correctly, then you should see all the command line options for c++filt command again `pacman -Syuu`
- After the second time, everything will be up to date. To install the MinGW toolchain, run
`pacman -S mingw-w64-x86_64-toolchain`. This will install the toolchain to your MSYS2 default installation path under
`C:\msys64\mingw64\bin`
- Add this path `C:\msys64\mingw64\bin` to windows global `PATH`
- Test by running `c++filt --help` from windows command prompt, if everything is set up correctly, then you should see
all the command line options for c++filt
# Setup and Configuration # Setup and Configuration
## Running compiler explorer on Windows ## Running compiler explorer on Windows
Refer to the [readme](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsNative.md) on running Native on Windows for general setup of Compiler Explorer and other compilers.
Refer to the [readme](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsNative.md) on running
Native on Windows for general setup of Compiler Explorer and other compilers.
## Setting up c++.local.properties ## Setting up c++.local.properties
The next step is to create a `c++.local.properties` file under `etc/config` folder.
The next step is going to be different for everyone, as you can choose what compiler options you pass to the compiler and so on, but im going to paste my template here, and you can just modify, what you need The next step is to create a `c++.local.properties` file under `etc/config` folder. The next step is going to be
different for everyone, as you can choose what compiler options you pass to the compiler and so on, but im going to
paste my template here, and you can just modify, what you need
``` ```
# Default settings for C++ # Default settings for C++
@@ -55,8 +75,11 @@ needsMulti=false
stubRe=\bmain\b stubRe=\bmain\b
stubText=int main(void){return 0;/*stub provided by Compiler Explorer*/} stubText=int main(void){return 0;/*stub provided by Compiler Explorer*/}
``` ```
**It's important to note that the `compiler.iar8.32.4.compilerType` field is set to `ewarm` this will be the custom compiler key later on**
**It's important to note that the `compiler.iar8.32.4.compilerType` field is set to `ewarm` this will be the custom
compiler key later on**
## Running Compiler Explorer ## Running Compiler Explorer
You should be able to just `cd` into the compiler explorer repository and run `npm start`. After that just head on to [localhost:10240](http://localhost:10240) You should be able to just `cd` into the compiler explorer repository and run `npm start`. After that just head on to
[localhost:10240](http://localhost:10240)

View File

@@ -2,27 +2,37 @@
Contact: [Ethan Slattery](https://github.com/CrustyAuklet) Contact: [Ethan Slattery](https://github.com/CrustyAuklet)
## Prerequisites ## Prerequisites
To run the IAR compiler for IAR on linux you will need the following things: To run the IAR compiler for IAR on linux you will need the following things:
- A valid copy of the IAR compiler
- A license for the compiler - A valid copy of the IAR compiler
- wine set up for win32 and i386 - A license for the compiler
- wine set up for win32 and i386
### Getting a copy of IAR ### Getting a copy of IAR
Assuming you already have a valid copy of IAR installed on a Windows machine, you can simply zip the installation directory.
The installation is "portable" for all use cases needed by compiler explorer. The one thing that doesn't work so far is building a project file. Individual file compilation works well using `iccavr.exe`.
If you installed to the default location this means creating an archive of the directory `C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0` Assuming you already have a valid copy of IAR installed on a Windows machine, you can simply zip the installation
directory. The installation is "portable" for all use cases needed by compiler explorer. The one thing that doesn't work
so far is building a project file. Individual file compilation works well using `iccavr.exe`.
If you installed to the default location this means creating an archive of the directory
`C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.0`
### Compiler license ### Compiler license
The machine used for compiling needs to have access to a license, or compilation will fail.
Ensure the server running compiler explorer can access the license server. If you want to use a dongle, then modify the following instructions accordingly, and good luck.
Note: Each time a compilation happens the machine doing that compilation claims the license for 20 minutes. The machine used for compiling needs to have access to a license, or compilation will fail. Ensure the server running
Each docker instance counts as a different machine. Because of this it is a good idea to ensure that the machine running IAR is a long-lived container/VM/machine to prevent using up all licenses and irritating your coworkers. compiler explorer can access the license server. If you want to use a dongle, then modify the following instructions
accordingly, and good luck.
Note: Each time a compilation happens the machine doing that compilation claims the license for 20 minutes. Each docker
instance counts as a different machine. Because of this it is a good idea to ensure that the machine running IAR is a
long-lived container/VM/machine to prevent using up all licenses and irritating your coworkers.
### Wine ### Wine
There are many places online to learn how to set up wine. A very simplified setup I often use in a fresh ubuntu docker container is:
There are many places online to learn how to set up wine. A very simplified setup I often use in a fresh ubuntu docker
container is:
```bash ```bash
$ apt-get update $ apt-get update
@@ -33,27 +43,32 @@ $ WINEARCH=win32 winecfg
``` ```
## Setup and Configuration ## Setup and Configuration
### Running locally on a Windows workstation or a windows server
Refer to the readme on running [Native on Windows](WindowsNative.md) for general setup of Compiler Explorer and other compilers.
Then add EWAVR as an additional compiler in your `c++.local.properties` file. The example in the compiler explorer
[documentation folder](EWAVR.properties) is written for linux so just modify the paths as needed.
The following properties are the ones that need to be set in addition to the typical settings you do for any compiler.
- `versionRe=^IAR C\/C\+\+ Compiler.*AVR$` ### Running locally on a Windows workstation or a windows server
- `isSemVer=true`
- `options=--eec++` Refer to the readme on running [Native on Windows](WindowsNative.md) for general setup of Compiler Explorer and other
- `supportsDemangler=false` compilers. Then add EWAVR as an additional compiler in your `c++.local.properties` file. The example in the compiler
explorer [documentation folder](EWAVR.properties) is written for linux so just modify the paths as needed. The following
properties are the ones that need to be set in addition to the typical settings you do for any compiler.
- `versionRe=^IAR C\/C\+\+ Compiler.*AVR$`
- `isSemVer=true`
- `options=--eec++`
- `supportsDemangler=false`
### Running on a linux server using docker ### Running on a linux server using docker
#### Step 1: provide configuration files, compilers, and libraries #### Step 1: provide configuration files, compilers, and libraries
*If you are more experienced with docker this can be done with a volume, but I just use a local folder on my server*
_If you are more experienced with docker this can be done with a volume, but I just use a local folder on my server_
Create a folder on the server `/opt/compiler_explorer`. We are focusing on EWAVR, but you can see we also include Create a folder on the server `/opt/compiler_explorer`. We are focusing on EWAVR, but you can see we also include
several other embedded compilers, the native compilers, and many open source and internal libraries. The EWAVR specific portions several other embedded compilers, the native compilers, and many open source and internal libraries. The EWAVR specific
of `c++.local.properties` is provided in the [example](EWAVR.properties), the rest is generic library and compiler settings. portions of `c++.local.properties` is provided in the [example](EWAVR.properties), the rest is generic library and
`compiler-explorer.local.properties` contains server specific sub-domain settings. compiler settings. `compiler-explorer.local.properties` contains server specific sub-domain settings.
The EWAVR directories are just the archives of the installation folders from windows un-tarred there, as you can see from the layout. The EWAVR directories are just the archives of the installation folders from windows un-tarred there, as you can see
from the layout.
```bash ```bash
/opt/compiler_explorer/ /opt/compiler_explorer/
@@ -90,8 +105,10 @@ The EWAVR directories are just the archives of the installation folders from win
``` ```
#### Step 2: Make iccavr callable #### Step 2: Make iccavr callable
To invoke `iccavr` you need to use the command `wine /opt/compiler_explorer/compilers/ewavr_7108/avr/bin/iccavr.exe` which created some issues for me in CE.
I create small bash script aliases using the following commands, for each versions `bin` folder: To invoke `iccavr` you need to use the command `wine /opt/compiler_explorer/compilers/ewavr_7108/avr/bin/iccavr.exe`
which created some issues for me in CE. I create small bash script aliases using the following commands, for each
versions `bin` folder:
```bash ```bash
$ IAR_ROOT=/opt/compiler_explorer/compilers/ewavr_7108 $ IAR_ROOT=/opt/compiler_explorer/compilers/ewavr_7108
@@ -101,9 +118,11 @@ $ echo -e "#\!/bin/bash\nwine $IAR_ROOT/avr/bin/iccavr.exe\n" > $IAR_ROOT/avr/bi
``` ```
#### Step 3: Start Compiler Explorer as a docker image #### Step 3: Start Compiler Explorer as a docker image
A [docker image](https://hub.docker.com/repository/docker/crustyauklet/compiler_explorer) is available that bundles a working version of Compiler Explorer
and wine so that no additional setup is needed on the host server. The IAR license needs to be run once, at system startup to register with the license server, A [docker image](https://hub.docker.com/repository/docker/crustyauklet/compiler_explorer) is available that bundles a
so that can be seen in the docker command. If you have multiple IAR versions, only one needs to be run, and it doesn't matter which one. working version of Compiler Explorer and wine so that no additional setup is needed on the host server. The IAR license
needs to be run once, at system startup to register with the license server, so that can be seen in the docker command.
If you have multiple IAR versions, only one needs to be run, and it doesn't matter which one.
```bash ```bash
$ IAR_SERVER=my.liscense_server.ip.address $ IAR_SERVER=my.liscense_server.ip.address

View File

@@ -1,9 +1,8 @@
Compiler Explorer and Privacy ## Compiler Explorer and Privacy
-----------------------------
*This is a summary of our Privacy policy, not a legal document, and might be incomplete.* _This is a summary of our Privacy policy, not a legal document, and might be incomplete._
*For the full Privacy policy, see `static/policies/privacy.html`, or visit https://godbolt.org/#privacy* _For the full Privacy policy, see `static/policies/privacy.html`, or visit https://godbolt.org/#privacy_
The main Compiler Explorer site (at https://godbolt.org/) has a cookie and privacy policy, and it's expected that any The main Compiler Explorer site (at https://godbolt.org/) has a cookie and privacy policy, and it's expected that any
changes to the code are in compliance with those policies. It's worth taking a look at them if you're touching any area changes to the code are in compliance with those policies. It's worth taking a look at them if you're touching any area
@@ -20,9 +19,9 @@ the sister site www.godbolt.ms and that data is covered by
Users have rights over the data they create: so in theory they could ask for any data stored on them to be removed. We Users have rights over the data they create: so in theory they could ask for any data stored on them to be removed. We
have no way of tracking data (a short link, perhaps) back to an individual user, and when I asked some experts on this have no way of tracking data (a short link, perhaps) back to an individual user, and when I asked some experts on this
the consensus was that we're OK not to supply this. If, however, we ever have user attribution (e.g., we start the consensus was that we're OK not to supply this. If, however, we ever have user attribution (e.g., we start having
having accounts), we need to support the user being able to close their account, and/or delete any data they created accounts), we need to support the user being able to close their account, and/or delete any data they created (e.g.,
(e.g., short links). All this makes perfect sense and would probably be done anyway, as it seems useful! short links). All this makes perfect sense and would probably be done anyway, as it seems useful!
We anonymise IP addresses so there's no exact mapping back to an individual using an IP. Not that it's trivial to map an We anonymise IP addresses so there's no exact mapping back to an individual using an IP. Not that it's trivial to map an
IP to a user anyway. IP to a user anyway.
@@ -37,10 +36,10 @@ is to not use the main Compiler Explorer but instead run their own local service
A very small group of people have administrator rights on the public Compiler Explorer. Those individuals can: A very small group of people have administrator rights on the public Compiler Explorer. Those individuals can:
* Read the logs - Read the logs
* Log in to the running Compiler Explorer compilation nodes - Log in to the running Compiler Explorer compilation nodes
* Access the S3 storage where caches and stored information may be kept - Access the S3 storage where caches and stored information may be kept
* Access and modify the EFS storage where compilers are stored - Access and modify the EFS storage where compilers are stored
In short, administrators can see everything that goes on. It is expected that administrators keep this deep In short, administrators can see everything that goes on. It is expected that administrators keep this deep
responsibility in mind when performing actions on Compiler Explorer, and that they keep users' privacy at the forefront responsibility in mind when performing actions on Compiler Explorer, and that they keep users' privacy at the forefront

View File

@@ -1,41 +1,48 @@
# How do I ? # How do I ?
This is a how-to guide for the user-interface presented by [Compiler Explorer](https://godbolt.org). This is a how-to guide for the user-interface presented by [Compiler Explorer](https://godbolt.org). This doesn't cover
This doesn't cover the details of how to set up or modify Compiler Explorer for your own needs. the details of how to set up or modify Compiler Explorer for your own needs. For that, please check the documents which
For that, please check the documents which already cover topics like: already cover topics like:
* [Adding a language](AddingALanguage.md)
* [Adding a compiler](AddingACompiler.md) - [Adding a language](AddingALanguage.md)
* [Adding a library](AddingALibrary.md) - [Adding a compiler](AddingACompiler.md)
* [Adding a tool](AddingATool.md) - [Adding a library](AddingALibrary.md)
* and many more at [compiler-explorer/docs](https://github.com/compiler-explorer/compiler-explorer/tree/main/docs) - [Adding a tool](AddingATool.md)
- and many more at [compiler-explorer/docs](https://github.com/compiler-explorer/compiler-explorer/tree/main/docs)
Fast links: Fast links:
- [How do I ?](#how-do-i-) - [How do I ?](#how-do-i-)
- [Change the assembly syntax from Intel](#change-the-assembly-syntax-from-intel) - [Change the assembly syntax from Intel](#change-the-assembly-syntax-from-intel)
- [Compare the time taken by compilation and networking](#compare-the-time-taken-by-compilation-and-networking) - [Compare the time taken by compilation and networking](#compare-the-time-taken-by-compilation-and-networking)
- [View intermediate information provided by the compilers](#view-intermediate-information-provided-by-the-compilers) - [View intermediate information provided by the compilers](#view-intermediate-information-provided-by-the-compilers)
## Change the assembly syntax from Intel ## Change the assembly syntax from Intel
![Output, intel and at&t](./images/asm_info.png) ![Output, intel and at&t](./images/asm_info.png)
The option to switch assembly from Intel to AT&T syntax is present in the `Output` option of each compiler. The option to switch assembly from Intel to AT&T syntax is present in the `Output` option of each compiler. If enough
If enough space is not present, the option also presents itself as the gear symbol (⚙) space is not present, the option also presents itself as the gear symbol (⚙)
## Compare the time taken by compilation and networking ## Compare the time taken by compilation and networking
![Brief overview of UI](./images/brief_overview.png) ![Brief overview of UI](./images/brief_overview.png)
This is the symbol that looks like a bar graph (📊). If your compilations are taking long, you can use this to check the time taken by: This is the symbol that looks like a bar graph (📊). If your compilations are taking long, you can use this to check the
* Networking, JavaScript, waiting for events, etc. time taken by:
* Checking the cache and retrieving from it on a cache-hit
* Compilation (on force compilation or cache-miss) - Networking, JavaScript, waiting for events, etc.
* Parsing the generated assembly before presenting it - Checking the cache and retrieving from it on a cache-hit
- Compilation (on force compilation or cache-miss)
- Parsing the generated assembly before presenting it
## View intermediate information provided by the compilers ## View intermediate information provided by the compilers
![Options for GCC](./images/add_new_gcc.png)
![Options for Clang](./images/add_new_clang.png)
Though both GCC and Clang create supplementary outputs along with assembly (shown by default), ![Options for GCC](./images/add_new_gcc.png) ![Options for Clang](./images/add_new_clang.png)
and an executable (created if an executor has been added), the exact nature of the outputs and their formats differ between the compilers.
GCC allows the Tree, IPA, RTL and graph outputs, while Clang allows optimization, AST, IR and graph outputs. Though both GCC and Clang create supplementary outputs along with assembly (shown by default), and an executable
Some outputs (e.g. RTL or graph) also have a rich set of options in the UI to enable focussing on a particular function or compiler stage. (created if an executor has been added), the exact nature of the outputs and their formats differ between the compilers.
GCC allows the Tree, IPA, RTL and graph outputs, while Clang allows optimization, AST, IR and graph outputs. Some
outputs (e.g. RTL or graph) also have a rich set of options in the UI to enable focussing on a particular function or
compiler stage.

View File

@@ -9,8 +9,7 @@ This document is an attempt to capture thoughts on the future direction of Compi
A number of the open issues are to add more languages, libraries and compilers. Continuing to make it easier for others A number of the open issues are to add more languages, libraries and compilers. Continuing to make it easier for others
to submit PRs to add new compilers is very important. This has improved, but not all compilers are installed using the to submit PRs to add new compilers is very important. This has improved, but not all compilers are installed using the
new approach. There's documentation on [adding a compiler](AddingACompiler.md), new approach. There's documentation on [adding a compiler](AddingACompiler.md),
[adding a new language](AddingALanguage.md) [adding a new language](AddingALanguage.md) and [adding a library](AddingALibrary.md).
and [adding a library](AddingALibrary.md).
### Multiple file support ### Multiple file support
@@ -29,6 +28,7 @@ improve code quality (e.g. move to transpiling from Typescript or similar to giv
easy to support existing code. easy to support existing code.
## Considerations ## Considerations
### Tensions ### Tensions
There's an inherent tension between the standalone, run-it-yourself version of CE and the scalable, AWS-backed CE There's an inherent tension between the standalone, run-it-yourself version of CE and the scalable, AWS-backed CE
@@ -50,19 +50,18 @@ that has been relaxed slightly to allow up to three company sponsor logos visibl
### 2021 goals ### 2021 goals
* **Login support**. Support logging in to the site with GitHub, Google, etc. We will _never_ force you to log in for - **Login support**. Support logging in to the site with GitHub, Google, etc. We will _never_ force you to log in for
basic features, and of course will update the Privacy Policy. I won't be selling anything to do with user info etc, basic features, and of course will update the Privacy Policy. I won't be selling anything to do with user info etc,
either: Logging in will be purely used to make _your_ life easier and allow you to manage things like shared settings either: Logging in will be purely used to make _your_ life easier and allow you to manage things like shared settings
and configuration, listing short URLs you've created (and potentially being able to remove them); and _maybe_ being and configuration, listing short URLs you've created (and potentially being able to remove them); and _maybe_ being
able to make user-named short URLs (e.g., "godbolt.org/u/mattgodbolt/ctad-example"). This goal is a personal pet able to make user-named short URLs (e.g., "godbolt.org/u/mattgodbolt/ctad-example"). This goal is a personal pet
project of [Matt's](http://github.com/mattgodbolt/). project of [Matt's](http://github.com/mattgodbolt/).
* **Multi-file support**. Multiple file compilation units to open the door to seeing LTO and maybe modules. This may - **Multi-file support**. Multiple file compilation units to open the door to seeing LTO and maybe modules. This may
include being able to use a `CMake` file to build things. include being able to use a `CMake` file to build things.
* **Modernising the codebase**. Moving the codebase to TypeScript, or something similar that will allow us to worry less - **Modernising the codebase**. Moving the codebase to TypeScript, or something similar that will allow us to worry less
about differences between front-end and back-end code (old Javascript versions), and help us attract more people to about differences between front-end and back-end code (old Javascript versions), and help us attract more people to
the project. the project.
* **More compilers and libraries**. Plus finishing off the last stragglers of installation. - **More compilers and libraries**. Plus finishing off the last stragglers of installation.
### Prior years' goals ### Prior years' goals

View File

@@ -1,9 +1,11 @@
# Sponsorship # Sponsorship
Compiler Explorer is funded by sponsors: mostly individuals through Patreon, GitHub sponsors and PayPal one-off payments. Compiler Explorer is funded by sponsors: mostly individuals through Patreon, GitHub sponsors and PayPal one-off
There is potential for corporate sponsorship; though extremely limited due to the goal of making Compiler Explorer a mostly ad-free experience. payments. There is potential for corporate sponsorship; though extremely limited due to the goal of making Compiler
Explorer a mostly ad-free experience.
Corporate sponsorship requests should be directed to [Matt](mailto:matt@godbolt.org), who has sole discretion on what kinds of sponsorship is appropriate. Corporate sponsorship requests should be directed to [Matt](mailto:matt@godbolt.org), who has sole discretion on what
kinds of sponsorship is appropriate.
## The sponsors.yaml format ## The sponsors.yaml format
@@ -26,7 +28,7 @@ levels:
- name: Level two - name: Level two
description: The second level. description: The second level.
sponsors: sponsors:
- bob - bob
- ian - ian
- joe - joe
``` ```

View File

@@ -1,10 +1,12 @@
# Using Systemd socket based activation to start Compiler Explorer # Using Systemd socket based activation to start Compiler Explorer
This document gives a short overview of how to use Systemd to automatically start Compiler Explorer when the web-interface is accessed. This document gives a short overview of how to use Systemd to automatically start Compiler Explorer when the
web-interface is accessed.
You'll need to create two files in `/etc/systemd/system/`: You'll need to create two files in `/etc/systemd/system/`:
compiler-explorer.socket: compiler-explorer.socket:
``` ```
[Socket] [Socket]
ListenStream=10240 ListenStream=10240
@@ -13,8 +15,8 @@ ListenStream=10240
WantedBy=sockets.target WantedBy=sockets.target
``` ```
compiler-explorer.service: compiler-explorer.service:
``` ```
[Service] [Service]
Type=simple Type=simple

View File

@@ -4,35 +4,24 @@ Contact: [Nicole Mazzuca](https://github.com/ubsan)
## Basic Setup ## Basic Setup
The setup on Windows should be fairly trivial: The setup on Windows should be fairly trivial: the only prerequisite is node. If you haven't yet installed node yet, you
the only prerequisite is node. can grab it from [here](https://nodejs.org/en/); get the Windows LTS release.
If you haven't yet installed node yet, you can grab it from
[here](https://nodejs.org/en/);
get the Windows LTS release.
Once you've done this, Once you've done this, and added `npm` to the path, run the following commands from any command line, in the directory
and added `npm` to the path, you want the Compiler Explorer (from here on, CE) to live:
run the following commands from any command line,
in the directory you want the Compiler Explorer (from here on, CE)
to live:
```bat ```bat
git clone https://github.com/compiler-explorer/compiler-explorer.git git clone https://github.com/compiler-explorer/compiler-explorer.git
``` ```
Then, we'll need to make a configuration file Then, we'll need to make a configuration file which points at your compilers and include directories. Copy
which points at your compilers and include directories. [`docs\WindowsLocal.properties`](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsLocal.properties)
Copy [`docs\WindowsLocal.properties`](https://github.com/compiler-explorer/compiler-explorer/blob/main/docs/WindowsLocal.properties) to a new file, to a new file, `etc\config\c++.local.properties`, and edit it, following the instructions in the comments. If you have
`etc\config\c++.local.properties`, and edit it, any questions, please ping me on discord.
following the instructions in the comments.
If you have any questions, please ping me on discord.
## Actually Running the danged thing ## Actually Running the danged thing
Once you've finished setting it up, Once you've finished setting it up, you can `cd` into the `compiler-explorer` directory, then run
you can `cd` into the `compiler-explorer` directory,
then run
```bat ```bat
npm install npm install
@@ -54,36 +43,36 @@ info: =======================================
Now point your favorite web browser at http://localhost:10240, and you should be done! Now point your favorite web browser at http://localhost:10240, and you should be done!
You only have to run `npm install` the first time; You only have to run `npm install` the first time; every time after that, you should just be able to run `npm start`.
every time after that, you should just be able to run `npm start`.
## Debugging using VSCode ## Debugging using VSCode
Similar to [WindowsSubsystemForLinux](WindowsSubsystemForLinux.md),
the following is a `launch.json` that works for attaching to an instance of CE that was launched with `npm run-script debugger` (launches with the `--inspect` flag).
Similar to [WindowsSubsystemForLinux](WindowsSubsystemForLinux.md), the following is a `launch.json` that works for
attaching to an instance of CE that was launched with `npm run-script debugger` (launches with the `--inspect` flag).
```json ```json
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"name": "Attach to Process", "name": "Attach to Process",
"port": 9229, "port": 9229,
"address": "localhost", "address": "localhost",
"protocol": "inspector", "protocol": "inspector",
"localRoot": "${workspaceRoot}", "localRoot": "${workspaceRoot}",
"remoteRoot": "C:\\Users\\${username}\\compiler-explorer" "remoteRoot": "C:\\Users\\${username}\\compiler-explorer"
} }
] ]
} }
``` ```
Launch CE with `npm run-script debugger` to have node listen on port 9229. Launch CE with `npm run-script debugger` to have node listen on port 9229.
Because this only attaches to the process, as opposed to launching the process, in order to debug startup code you need to attach while npm is starting up. Because this only attaches to the process, as opposed to launching the process, in order to debug startup code you need
The `debugger` script also enables `debug` logging level so debug print statements can be seen during the CE startup and run. to attach while npm is starting up. The `debugger` script also enables `debug` logging level so debug print statements
can be seen during the CE startup and run.
### Setting up binary mode and execution ### Setting up binary mode and execution
@@ -91,36 +80,39 @@ To create executables with Visual C++, it's required to install the Windows SDK.
You can find the Windows 10 SDK [here](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk) You can find the Windows 10 SDK [here](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk)
When you've installed the SDK, you'll need to set up the library and include paths in Compilers Explorer. When you've installed the SDK, you'll need to set up the library and include paths in Compilers Explorer. Make sure that
Make sure that in the previously discussed c++.local.properties you have added at least: in the previously discussed c++.local.properties you have added at least:
* to includePath
- Windows Kits/10/include/*version*/ucrt
- Windows Kits/10/include/*version*/shared
- Windows Kits/10/include/*version*/um
* to libPath (for the x64 compiler)
- Windows Kits/10/Lib/*version*/um/x64
- Windows Kits/10/Lib/*version*/ucrt/x64
- VC installation path/lib/x64
If needed, you can set in your properties file: ```supportsExecute=true``` - to includePath
- Windows Kits/10/include/_version_/ucrt
- Windows Kits/10/include/_version_/shared
- Windows Kits/10/include/_version_/um
- to libPath (for the x64 compiler)
- Windows Kits/10/Lib/_version_/um/x64
- Windows Kits/10/Lib/_version_/ucrt/x64
- VC installation path/lib/x64
If needed, you can set in your properties file: `supportsExecute=true`
#### Binary mode #### Binary mode
For binary mode, you will need a Windows version of Objdump. There are various For binary mode, you will need a Windows version of Objdump. There are various versions of MingW available that will
versions of MingW available that will offer binutils including objdump. offer binutils including objdump.
The version of objdump that we have tested with is shipped with MingW-64, The version of objdump that we have tested with is shipped with MingW-64, you can find it for download
you can find it for download [here](https://sourceforge.net/projects/mingw-w64/) [here](https://sourceforge.net/projects/mingw-w64/)
When you use the installer for MingW-64, make sure you select the right architecture during installation. When you use the installer for MingW-64, make sure you select the right architecture during installation.
When you use the zipped version, after unzipping you will need to add the bin folder to your Windows PATHS environment variable. When you use the zipped version, after unzipping you will need to add the bin folder to your Windows PATHS environment
Be aware that this PATH needs to be added before any other folders that might contain an objdump. You cannot just point to the .exe as the objdumper without having the proper PATH set, it will not work. variable. Be aware that this PATH needs to be added before any other folders that might contain an objdump. You cannot
just point to the .exe as the objdumper without having the proper PATH set, it will not work.
When you have everything installed, you can add to your properties file the following: When you have everything installed, you can add to your properties file the following:
``` ```
supportsBinary=true supportsBinary=true
objdumper=objdump objdumper=objdump
``` ```
*Note that the 32 bit version of MingW does not support 64 bit binaries.* _Note that the 32 bit version of MingW does not support 64 bit binaries._

View File

@@ -2,26 +2,43 @@
Contact: [@AndrewPardoe](https://github.com/AndrewPardoe) Contact: [@AndrewPardoe](https://github.com/AndrewPardoe)
The Compiler Explorer ("CE" from here on) runs quite well on the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/faq) ("WSL"). The Compiler Explorer ("CE" from here on) runs quite well on the
Running on WSL enables Linux-based compilers to continue running natively while enabling Windows-based compilers to run in a real Windows environment. [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/faq) ("WSL"). Running on WSL enables
Linux-based compilers to continue running natively while enabling Windows-based compilers to run in a real Windows
environment.
No special configuration is needed to run CE under WSL. Some configuration is required for hosting the Microsoft Visual C++ ("MSVC") compiler. No special configuration is needed to run CE under WSL. Some configuration is required for hosting the Microsoft Visual
Testing has mainly been done on the Ubuntu distro but any distro should work. C++ ("MSVC") compiler. Testing has mainly been done on the Ubuntu distro but any distro should work.
## WSL/Windows interop and its limitations ## WSL/Windows interop and its limitations
WSL offers rich interop with Windows processes. You can run any Windows executable, such as "`cl.exe`", from a bash shell. But this interop capability has some limitations.
- Windows volumes: While Windows executables can be run from bash, they cannot see Linux volumes. Windows executables that need to read or write files must be run on a Windows volume. This means all MSVC compiles must be done in the Windows `%TEMP%` directory instead of in the `bash` environment's temp directory. WSL offers rich interop with Windows processes. You can run any Windows executable, such as "`cl.exe`", from a bash
- Path: The WSL path set in bash prepends the Windows path. While Linux filesystems support odd naming conventions such as spaces and parentheses, Windows' path uses these as a matter of course (e.g., `c:\Program Files (x86)`). Additionally, the Windows path delimiter is `\` instead of `/`, and it uses drive letters instead of mount points that are separated with a colon. shell. But this interop capability has some limitations.
- Path names: A Windows path of `c:\tmp` is normally referred to as `/mnt/c/tmp` in `bash`. However, users can customize their `drvfs` mount points. A tool is provided in newer Windows releases, `/bin/wslpath`, that will convert paths between systems. Code in CE currently does the conversion between the standard conventions using string manipulation.
- Environment variables: While the Windows path is available in bash, Windows environment variables are not. CE uses `cmd.exe /c echo %TEMP%` to determine the Windows temporary directory. - Windows volumes: While Windows executables can be run from bash, they cannot see Linux volumes. Windows executables
- Execution environment: The execution environment cannot currently be set when doing `childprocess.spawn`. This is a serious issue for the MSVC compiler, which is highly environment-dependent (e.g., `%INCLUDE%`, `%LIBPATH%`, etc.) that need to read or write files must be run on a Windows volume. This means all MSVC compiles must be done in the
Windows `%TEMP%` directory instead of in the `bash` environment's temp directory.
- Path: The WSL path set in bash prepends the Windows path. While Linux filesystems support odd naming conventions such
as spaces and parentheses, Windows' path uses these as a matter of course (e.g., `c:\Program Files (x86)`).
Additionally, the Windows path delimiter is `\` instead of `/`, and it uses drive letters instead of mount points that
are separated with a colon.
- Path names: A Windows path of `c:\tmp` is normally referred to as `/mnt/c/tmp` in `bash`. However, users can customize
their `drvfs` mount points. A tool is provided in newer Windows releases, `/bin/wslpath`, that will convert paths
between systems. Code in CE currently does the conversion between the standard conventions using string manipulation.
- Environment variables: While the Windows path is available in bash, Windows environment variables are not. CE uses
`cmd.exe /c echo %TEMP%` to determine the Windows temporary directory.
- Execution environment: The execution environment cannot currently be set when doing `childprocess.spawn`. This is a
serious issue for the MSVC compiler, which is highly environment-dependent (e.g., `%INCLUDE%`, `%LIBPATH%`, etc.)
## Configuration ## Configuration
This section is intended for the many WSL users who are new to Linux.
This section is intended for the many WSL users who are new to Linux.
If you plan on debugging CE, you should clone the CE repo on a Windows volume. If you plan on debugging CE, you should clone the CE repo on a Windows volume.
CE is built on node.js ("node"). The easiest way to install node is using NVM, the Node Version Manager. Run the following commands from a bash shell: CE is built on node.js ("node"). The easiest way to install node is using NVM, the Node Version Manager. Run the
following commands from a bash shell:
- `apt-get update` to make sure apt is up-to-date - `apt-get update` to make sure apt is up-to-date
- `apt-get install build-essential libssl-dev`, though you probably have these already - `apt-get install build-essential libssl-dev`, though you probably have these already
- Check https://github.com/creationix/nvm/releases for the latest NVM release, substituting it in the next command. - Check https://github.com/creationix/nvm/releases for the latest NVM release, substituting it in the next command.
@@ -30,7 +47,8 @@ CE is built on node.js ("node"). The easiest way to install node is using NVM, t
- `nvm ls-remote --lts` to show the latest long-term supported (LTS) version of node.js - `nvm ls-remote --lts` to show the latest long-term supported (LTS) version of node.js
- `nvm install 10.15.3`, substituting the latest LTS version, to install node.js - `nvm install 10.15.3`, substituting the latest LTS version, to install node.js
At this point you can change into the directory where you cloned CE and `make`. `make` will install a bunch of node packages and will finish with a message similar to this: At this point you can change into the directory where you cloned CE and `make`. `make` will install a bunch of node
packages and will finish with a message similar to this:
``` ```
info: ======================================= info: =======================================
@@ -46,49 +64,71 @@ Now you can point your favorite web browser at http://localhost:10240 and see yo
CE only required a few changes in order to run properly under WSL. Those changes are listed here: CE only required a few changes in order to run properly under WSL. Those changes are listed here:
- `app.js`: - `app.js`:
- `process.env.wsl` is set if CE if the string "Microsoft" in found in the output of `uname -a`. This works for all WSL distros as they all run on the base Microsoft Linux kernel. - `process.env.wsl` is set if CE if the string "Microsoft" in found in the output of `uname -a`. This works for all
- If the `-tmpDir` option is specified on the command line, both `process.env.tmpDir` and `process.env.winTmp` are set to the specified value Note that if this is specified as a non-Windows volume, Windows executables will fail to run properly. Otherwise, `process.env.winTmp` is set to the value of the Windows `%TEMP%` directory. WSL distros as they all run on the base Microsoft Linux kernel.
- `lib/exec.js`: Execute the compiler in the temporary directory. If the compiler's binary is located on a mounted volume (`startsWith("/mnt"`)) and CE is running under WSL, run the compiler in the `winTmp` directory. Otherwise, use the Linux temp directory. - If the `-tmpDir` option is specified on the command line, both `process.env.tmpDir` and `process.env.winTmp` are set
- `lib/compilers/wsl-vc.js`: See also `wine-vc.js`, the Wine version of this compiler-specific file. These files provide custom behaviors for a compiler. This file does two interesting things: to the specified value Note that if this is specified as a non-Windows volume, Windows executables will fail to run
- The `CompileCl` function translates from Linux-style directories to Windows-style directories (`/mnt/c/tmp` to `c:/tmp`) so that `CL.exe` can find its input files. properly. Otherwise, `process.env.winTmp` is set to the value of the Windows `%TEMP%` directory.
- The `newTempDir` function creates a temporary directory in `winTmp`. CEs creates directories under the temp directory that start with `compiler-explorer-compiler` where the compiler and compiler output lives. This is similar to the function in `lib/base-compiler.js`. - `lib/exec.js`: Execute the compiler in the temporary directory. If the compiler's binary is located on a mounted
- `etc/config/c++.defaults.properties`: Add a configuration (`&cl19`) for MSVC compilers. This edits in here are currently wrong in two ways, but it doesn't affect the main CE instance as it uses `amazon` properties files, and it doesn't affect anyone running a local copy of CE because CE will just fail silently when it can't find a compiler. volume (`startsWith("/mnt"`)) and CE is running under WSL, run the compiler in the `winTmp` directory. Otherwise, use
- The locations of these are hardcoded to a particular install location. See **MSVC setup** below for more information. the Linux temp directory.
- Setting of the `%INCLUDE%` path is done with the `/I` switch. This is very clunky and will fall over when command-line limits are hit, but it's the only option currently as environments aren't passed through when starting a Windows process from WSL. - `lib/compilers/wsl-vc.js`: See also `wine-vc.js`, the Wine version of this compiler-specific file. These files provide
custom behaviors for a compiler. This file does two interesting things:
- The `CompileCl` function translates from Linux-style directories to Windows-style directories (`/mnt/c/tmp` to
`c:/tmp`) so that `CL.exe` can find its input files.
- The `newTempDir` function creates a temporary directory in `winTmp`. CEs creates directories under the temp
directory that start with `compiler-explorer-compiler` where the compiler and compiler output lives. This is similar
to the function in `lib/base-compiler.js`.
- `etc/config/c++.defaults.properties`: Add a configuration (`&cl19`) for MSVC compilers. This edits in here are
currently wrong in two ways, but it doesn't affect the main CE instance as it uses `amazon` properties files, and it
doesn't affect anyone running a local copy of CE because CE will just fail silently when it can't find a compiler.
- The locations of these are hardcoded to a particular install location. See **MSVC setup** below for more
information.
- Setting of the `%INCLUDE%` path is done with the `/I` switch. This is very clunky and will fall over when
command-line limits are hit, but it's the only option currently as environments aren't passed through when starting
a Windows process from WSL.
## Debugging ## Debugging
The only viable option for debugging under WSL is to use [VS Code](https://code.visualstudio.com). Because VS Code doesn't currently run natively under WSL, you have to attach to a running CE instance. The following is a `launch.json` that works for attaching to an instance of CE that was launched with the `--inspect` flag. The only viable option for debugging under WSL is to use [VS Code](https://code.visualstudio.com). Because VS Code
doesn't currently run natively under WSL, you have to attach to a running CE instance. The following is a `launch.json`
that works for attaching to an instance of CE that was launched with the `--inspect` flag.
```json ```json
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"name": "Attach to Process", "name": "Attach to Process",
"port": "9229", "port": "9229",
"address": "localhost", "address": "localhost",
"protocol": "inspector", "protocol": "inspector",
"localRoot": "${workspaceRoot}", "localRoot": "${workspaceRoot}",
"remoteRoot": "/mnt/c/src/compiler-explorer" "remoteRoot": "/mnt/c/src/compiler-explorer"
} }
] ]
} }
``` ```
Launch CE with `make NODE_ARGS="--inspect"` to have node listen on port 9229. Launch CE with `make NODE_ARGS="--inspect"` to have node listen on port 9229.
Because you can only attach to the process, as opposed to launching the process, you're limited to `printf` debugging for startup code. Search the code for `logger.info` to see examples of how to `printf` debug. Because you can only attach to the process, as opposed to launching the process, you're limited to `printf` debugging
for startup code. Search the code for `logger.info` to see examples of how to `printf` debug.
## MSVC setup ## MSVC setup
TODO. There's no real MSVC setup at this point because there's no good way to pass the environment to an invocation of `CL.exe`. Just point the `properties` file at your compiler binary and hack on the `/I` options until something works. TODO. There's no real MSVC setup at this point because there's no good way to pass the environment to an invocation of
`CL.exe`. Just point the `properties` file at your compiler binary and hack on the `/I` options until something works.
When I get this working in a generalized fashion, CE's config will expect that MSVC drops match the format used by the daily NuGet compiler drops at https://visualcpp.myget/org. (NuGet packages are just renamed ZIP files plus metadata so they make an easy distribution method for compiler toolset drops.) When I get this working in a generalized fashion, CE's config will expect that MSVC drops match the format used by the
daily NuGet compiler drops at https://visualcpp.myget/org. (NuGet packages are just renamed ZIP files plus metadata so
they make an easy distribution method for compiler toolset drops.)
## Putting it all together ## Putting it all together
This should be enough information to get you started running CE under WSL. If there's information that you wish you would have had, please submit a PR to document. If there's information you're lacking to get running, please enter an Issue on the CE repo or contact me directly. This should be enough information to get you started running CE under WSL. If there's information that you wish you
would have had, please submit a PR to document. If there's information you're lacking to get running, please enter an
Issue on the CE repo or contact me directly.

View File

@@ -1,51 +1,68 @@
Adding a library that is linked against: Adding a library that is linked against:
- If the library is a C shared library, you should not use these instructions, use the `after_staging_script` instead to build the library during the installation - If the library is a C shared library, you should not use these instructions, use the `after_staging_script` instead to
build the library during the installation
- Check what buildsystem is used. - Check what buildsystem is used.
- If CMake, it's going to be relatively easy. - If CMake, it's going to be relatively easy.
- If something else, it's going to be complicated. - If something else, it's going to be complicated.
- If CMake - If CMake
- If the CMakeLists.txt is in the root folder, everything should be work - If the CMakeLists.txt is in the root folder, everything should be work
- However, at least prefer to include make_targets property in the yaml to avoid any automagick confusion (it would test library name in all kinds of variants and when all fails do make all) - However, at least prefer to include make_targets property in the yaml to avoid any automagick confusion (it would
test library name in all kinds of variants and when all fails do make all)
- If there are multiple ways of generating libraries (shared/static), make a choice here - If there are multiple ways of generating libraries (shared/static), make a choice here
1. Add to bin/yaml/libraries.yaml 1. Add to bin/yaml/libraries.yaml
- There's a difference between nightly trunks' and versions, search for "nightly:" to find the nightlies
- Note: the name of the library in the yaml file needs to be the same as the name in the c++.amazon.properties file - There's a difference between nightly trunks' and versions, search for "nightly:" to find the nightlies
- Add basic entry - Note: the name of the library in the yaml file needs to be the same as the name in the c++.amazon.properties file
``` - Add basic entry
unifex:
type: github ```yaml
method: nightlyclone unifex:
repo: facebookexperimental/libunifex type: github
build_type: cmake method: nightlyclone
make_targets: repo: facebookexperimental/libunifex
- unifex build_type: cmake
targets: make_targets:
- trunk - unifex
targets:
- trunk
``` ```
2. Test installing 2. Test installing
- `bin/ce_install --enable nightly install 'unifex'`
- `bin/ce_install --enable nightly install 'unifex'`
3. Test building 3. Test building
- Make sure you have a compiler installed, for example via `bin/ce_install install 'gcc 10.1.0'`
- `bin/ce_install --enable nightly --buildfor g101 --dry build 'unifex'` - Make sure you have a compiler installed, for example via `bin/ce_install install 'gcc 10.1.0'`
- check one of the buildfolders that are created and see if there are .so's or .a's and otherwise check the cecmakelog.txt and cemakelog_X.txt - `bin/ce_install --enable nightly --buildfor g101 --dry build 'unifex'`
- Iterate over this to make it work - check one of the buildfolders that are created and see if there are .so's or .a's and otherwise check the
cecmakelog.txt and cemakelog_X.txt
- Iterate over this to make it work
4. If a static link file has been produced: 4. If a static link file has been produced:
- Add to the `c++.amazon.properties` in compiler-explorer in the libs properties for the new library a `libs.libraryname.staticliblink=libraryname`
- libraryname here is without the 'lib' prefix of the .a file - Add to the `c++.amazon.properties` in compiler-explorer in the libs properties for the new library a
- Example unifex `libs.libraryname.staticliblink=libraryname`
``` - libraryname here is without the 'lib' prefix of the .a file
- Example unifex
```ini
libs.unifex.name=libunifex libs.unifex.name=libunifex
libs.unifex.versions=trunk libs.unifex.versions=trunk
libs.unifex.staticliblink=unifex libs.unifex.staticliblink=unifex
libs.unifex.versions.trunk.version=trunk libs.unifex.versions.trunk.version=trunk
libs.unifex.versions.trunk.path=/opt/compiler-explorer/libs/unifex/trunk/include libs.unifex.versions.trunk.path=/opt/compiler-explorer/libs/unifex/trunk/include
``` ```
5. If a config header file has been generated based on the compiler configuration, we can only maybe support this if the header does NOT include any defines about the architecture.
5. If a config header file has been generated based on the compiler configuration, we can only maybe support this if the
header does NOT include any defines about the architecture.
6. Send PR's 6. Send PR's
7. Merge the amazon.properties to main 7. Merge the amazon.properties to main
8. Start library builder for the new library until no later than 00:00 UTC 8. Start library builder for the new library until no later than 00:00 UTC
9. Await and check libraries @ https://conan.compiler-explorer.com/libraries.html and logs @ https://conan.compiler-explorer.com/failedbuilds.html 9. Await and check libraries @ https://conan.compiler-explorer.com/libraries.html and logs @
- These new libraries won't show up on these pages until you do https://conan.compiler-explorer.com/reinitialize and then go to https://conan.compiler-explorer.com/libraries and hit refresh https://conan.compiler-explorer.com/failedbuilds.html
- These new libraries won't show up on these pages until you do https://conan.compiler-explorer.com/reinitialize and
then go to https://conan.compiler-explorer.com/libraries and hit refresh

View File

@@ -1,9 +1,10 @@
## Brief notes on how to build a compiler ## Brief notes on how to build a compiler
* log into admin node `ce admin` - log into admin node `ce admin`
* start the builder node: `ce builder start` - start the builder node: `ce builder start`
* log into builder node: `ce builder login` - log into builder node: `ce builder login`
* sudo docker run --rm --name gcc.build -v/home/ubuntu/.s3cfg:/root/.s3cfg:ro -ti compilerexplorer/gcc-builder bash build.sh 8.2.0 s3://compiler-explorer/opt/ - sudo docker run --rm --name gcc.build -v/home/ubuntu/.s3cfg:/root/.s3cfg:ro -ti compilerexplorer/gcc-builder bash
* Remember to stop the builder node! build.sh 8.2.0 s3://compiler-explorer/opt/
* Log out of the builder node - Remember to stop the builder node!
* `ce builder stop` - Log out of the builder node
- `ce builder stop`

View File

@@ -1,23 +1,26 @@
# Frontend testing # Frontend testing
We have a mixture of typescript in the main website's code (located in `static/tests`) and Cypress (located in `cypress/integration`) to test and report on the workings of that code. We have a mixture of typescript in the main website's code (located in `static/tests`) and Cypress (located in
`cypress/integration`) to test and report on the workings of that code.
But there's always the possibility to use Cypress code to do UI checks and testing. But there's always the possibility to use Cypress code to do UI checks and testing.
## Recommended ## Recommended
The recommended way of testing is to use typescript to test the inner workings of the various interfaces that are available. The recommended way of testing is to use typescript to test the inner workings of the various interfaces that are
available.
This has the advantage of having types and being able to verify your code is consistent with the rest of the website and probably going to run correctly - without having to startup the website and Cypress. This has the advantage of having types and being able to verify your code is consistent with the rest of the website and
probably going to run correctly - without having to startup the website and Cypress.
## Adding a test ## Adding a test
Steps to add a test: Steps to add a test:
* Create a new file in `static/tests` (copy paste from `static/tests/hello-world.ts`) - Create a new file in `static/tests` (copy paste from `static/tests/hello-world.ts`)
* Make sure to change the `description` as well as the test - Make sure to change the `description` as well as the test
* Add the file to the imports of `static/tests/_all.js` - Add the file to the imports of `static/tests/_all.js`
* Add a `runFrontendTest()` call with the new test description to `cypress/integration/frontend-testing.js` - Add a `runFrontendTest()` call with the new test description to `cypress/integration/frontend-testing.js`
## Starting tests locally ## Starting tests locally
@@ -25,4 +28,5 @@ You don't need to install an entire X server to actually run cypress (just xfvb)
You can find a complete list at https://docs.cypress.io/guides/getting-started/installing-cypress#System-requirements You can find a complete list at https://docs.cypress.io/guides/getting-started/installing-cypress#System-requirements
If you have the prerequisites installed, you should be able to run `npx cypress run` - however, you will need to start the CE website separately in another terminal before that. If you have the prerequisites installed, you should be able to run `npx cypress run` - however, you will need to start
the CE website separately in another terminal before that.

View File

@@ -1,52 +1,40 @@
# This document is a Work in Progress # This document is a Work in Progress
This document pretends to put everything that is important to check before doing a full site release as well as to how
to do it, to ensure that the site fully works upon the release of a new version.
This document pretends to put everything that is important to check Depending on the nature of the changes, only some sections of this list will be relevant - Feel free to focus only on
before doing a full site release as well as to how to do it, those you deem most important.
to ensure that the site fully works upon the release of a new version.
Depending on the nature of the changes, only some sections If you think we are missing any important point, we greatly appreciate suggestions.
of this list will be relevant - Feel free to focus only on those
you deem most important.
If you think we are missing any important point, we greatly appreciate
suggestions.
## Running the site ## Running the site
First things first, we'll use the beta environment as it lets us run the
site under additional checks that will automate some of the problem First things first, we'll use the beta environment as it lets us run the site under additional checks that will automate
detections for us. some of the problem detections for us.
To run the new version on the beta environment we'll use the `ce` utility: To run the new version on the beta environment we'll use the `ce` utility:
Ensure that the beta environment is active by running Ensure that the beta environment is active by running `ce --env beta environment start` - You can skip this step if it's
`ce --env beta environment start` - You can skip this step if it's already running from a previous run or if you'd rather boot it once the current version is marked as active.
already running from a previous run or if you'd rather boot it once
the current version is marked as active.
Check what `versionId` the desired commit has. This can be checked on the Check what `versionId` the desired commit has. This can be checked on the Github CI build logs as its build number for
Github CI build logs as its build number for that specific commit, or that specific commit, or by running `ce --env beta builds list` which shows a list of the most recent builds with their
by running `ce --env beta builds list` which shows a list of the corresponding commit hash.
most recent builds with their corresponding commit hash.
Once you have the desired `versionId`, mark it as the current version to Once you have the desired `versionId`, mark it as the current version to be used by running
be used by running `ce --env beta builds set_current {versionId}` `ce --env beta builds set_current {versionId}`
If needed, you can now restart the currently running instances If needed, you can now restart the currently running instances with `ce --env beta instances restart` if needed.
with `ce --env beta instances restart` if needed.
Once this is finished, the `/beta` endpoint should be ready for testing. Once this is finished, the `/beta` endpoint should be ready for testing.
- The first issue you might find is that the beta instance does not boot. - The first issue you might find is that the beta instance does not boot. This might be caused by the
This might be caused by the `--ensureNoIdClash` flag shutting the app down `--ensureNoIdClash` flag shutting the app down if it detects one or more pairs of compilers sharing the same id even
if it detects one or more pairs of compilers sharing the same id if they belong to different languages. An error should be logged with the culprits for easy debugging.
even if they belong to different languages. An error should be logged
with the culprits for easy debugging.
## Basic general site functionality ## Basic general site functionality
In-depth documentation follows below, but once the beta site is running,
some basic checks include:
- In-depth documentation follows below, but once the beta site is running, some basic checks include:
-

View File

@@ -1,9 +1,11 @@
If you need to update the x86 asm documentation, just run `etc/scripts/docenizers/docenizer.py`, which requires: If you need to update the x86 asm documentation, just run `etc/scripts/docenizers/docenizer.py`, which requires:
- Python 3.x with BeautifulSoup
- Python 3.x with BeautifulSoup
You can use some options in the script: You can use some options in the script:
- `-o`/`--outputpath` - Final destination of the generated JavaScript file
- `-i`/`--inputfolder` - Points to the downloaded and extracted .html files - `-o`/`--outputpath` - Final destination of the generated JavaScript file
- `-d`/`--downloadfolder` - Points to the download folder to use in case a new version is needed - `-i`/`--inputfolder` - Points to the downloaded and extracted .html files
- `-d`/`--downloadfolder` - Points to the download folder to use in case a new version is needed
Now you only need to run it, and hope for the best. Please report any problems you encounter Now you only need to run it, and hope for the best. Please report any problems you encounter

View File

@@ -5,19 +5,24 @@ The library build status is accessible from https://conan.compiler-explorer.com/
The build process of libraries (started by https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh) The build process of libraries (started by https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh)
has a couple of safeguards to not build libraries allday everyday, namely: has a couple of safeguards to not build libraries allday everyday, namely:
* The compiler needs to have supportsBinary=true on in the current https://github.com/compiler-explorer/compiler-explorer/blob/main/etc/config/c%2B%2B.amazon.properties - The compiler needs to have supportsBinary=true on in the current
* If all libraries are being built, only a commit hash change will result in a new build. https://github.com/compiler-explorer/compiler-explorer/blob/main/etc/config/c%2B%2B.amazon.properties
* If a particular compiler has failed to produce a valid build, it will be marked and will not build the library with this compiler anymore. - If all libraries are being built, only a commit hash change will result in a new build.
* There are a couple of hardcoded exceptions that never attempt the build, these can be found in https://github.com/compiler-explorer/infra/blob/main/bin/lib/library_builder.py#L29 - If a particular compiler has failed to produce a valid build, it will be marked and will not build the library with
* You can manually trigger a forced-build, by setting the `--build-for=compilerid` parameter, which can also be set by changing the 2nd parameter here -> https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh#L104 this compiler anymore.
* If you want to trigger all compilers to rebuild a certain library, you will need to manually delete the logging related to this library. - There are a couple of hardcoded exceptions that never attempt the build, these can be found in
https://github.com/compiler-explorer/infra/blob/main/bin/lib/library_builder.py#L29
- You can manually trigger a forced-build, by setting the `--build-for=compilerid` parameter, which can also be set by
changing the 2nd parameter here -> https://github.com/compiler-explorer/infra/blob/main/admin-daily-builds.sh#L104
- If you want to trigger all compilers to rebuild a certain library, you will need to manually delete the logging
related to this library.
# manually delete logging # manually delete logging
You have to login to the conan instance and delete records from the sqlite database responsible for keeping the logging. You have to login to the conan instance and delete records from the sqlite database responsible for keeping the logging.
Example: Example:
``` ```
ce conan login ce conan login
sudo -u ce sqlite3 /home/ce/.conan_server/buildslogs.db sudo -u ce sqlite3 /home/ce/.conan_server/buildslogs.db

View File

@@ -22,8 +22,8 @@
// 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.
export { Amd64DocumentationProvider } from './amd64'; export {Amd64DocumentationProvider} from './amd64';
export { Arm32DocumentationProvider } from './arm32'; export {Arm32DocumentationProvider} from './arm32';
export { AvrDocumentationProvider } from './avr'; export {AvrDocumentationProvider} from './avr';
export { JavaDocumentationProvider } from './java'; export {JavaDocumentationProvider} from './java';
export { Mos6502DocumentationProvider } from './mos6502'; export {Mos6502DocumentationProvider} from './mos6502';

View File

@@ -22,12 +22,14 @@
// 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.
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base'; import {AssemblyInstructionInfo, BaseAssemblyDocumentationProvider} from './base';
import { getAsmOpcode } from './generated/asm-docs-amd64'; import {getAsmOpcode} from './generated/asm-docs-amd64';
export class Amd64DocumentationProvider extends BaseAssemblyDocumentationProvider { export class Amd64DocumentationProvider extends BaseAssemblyDocumentationProvider {
private static readonly ATT_SUFFIX_REMOVER = /^([a-z]+)[blqw]$/i; private static readonly ATT_SUFFIX_REMOVER = /^([a-z]+)[blqw]$/i;
public static get key() { return 'amd64'; } public static get key() {
return 'amd64';
}
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null { public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
// Try both raw opcode and with AT&T suffix removed // Try both raw opcode and with AT&T suffix removed
let info = getAsmOpcode(instruction); let info = getAsmOpcode(instruction);

View File

@@ -22,11 +22,13 @@
// 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.
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base'; import {AssemblyInstructionInfo, BaseAssemblyDocumentationProvider} from './base';
import { getAsmOpcode } from './generated/asm-docs-avr'; import {getAsmOpcode} from './generated/asm-docs-avr';
export class AvrDocumentationProvider extends BaseAssemblyDocumentationProvider { export class AvrDocumentationProvider extends BaseAssemblyDocumentationProvider {
public static get key() { return 'avr'; } public static get key() {
return 'avr';
}
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null { public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
return getAsmOpcode(instruction) || null; return getAsmOpcode(instruction) || null;
} }

View File

@@ -22,11 +22,11 @@
// 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.
import { makeKeyedTypeGetter } from '../keyed-type'; import {makeKeyedTypeGetter} from '../keyed-type';
import * as all from './_all'; import * as all from './_all';
export { BaseAssemblyDocumentationProvider } from './base'; export {BaseAssemblyDocumentationProvider} from './base';
export * from './_all'; export * from './_all';
export const getDocumentationProviderTypeByKey = makeKeyedTypeGetter('documentation provider', all); export const getDocumentationProviderTypeByKey = makeKeyedTypeGetter('documentation provider', all);

View File

@@ -22,11 +22,13 @@
// 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.
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base'; import {AssemblyInstructionInfo, BaseAssemblyDocumentationProvider} from './base';
import { getAsmOpcode } from './generated/asm-docs-java'; import {getAsmOpcode} from './generated/asm-docs-java';
export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider { export class JavaDocumentationProvider extends BaseAssemblyDocumentationProvider {
public static get key() { return 'java'; } public static get key() {
return 'java';
}
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null { public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
return getAsmOpcode(instruction) || null; return getAsmOpcode(instruction) || null;
} }

View File

@@ -22,11 +22,13 @@
// 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.
import { AssemblyInstructionInfo, BaseAssemblyDocumentationProvider } from './base'; import {AssemblyInstructionInfo, BaseAssemblyDocumentationProvider} from './base';
import { getAsmOpcode } from './generated/asm-docs-6502'; import {getAsmOpcode} from './generated/asm-docs-6502';
export class Mos6502DocumentationProvider extends BaseAssemblyDocumentationProvider { export class Mos6502DocumentationProvider extends BaseAssemblyDocumentationProvider {
public static get key() { return '6502'; } public static get key() {
return '6502';
}
public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null { public override getInstructionInformation(instruction: string): AssemblyInstructionInfo | null {
return getAsmOpcode(instruction) || null; return getAsmOpcode(instruction) || null;
} }

View File

@@ -24,7 +24,7 @@
import AWS from 'aws-sdk'; import AWS from 'aws-sdk';
import { logger } from './logger'; import {logger} from './logger';
export class InstanceFetcher { export class InstanceFetcher {
constructor(properties) { constructor(properties) {
@@ -37,12 +37,10 @@ export class InstanceFetcher {
async getInstances() { async getInstances() {
const result = await this.ec2.describeInstances().promise(); const result = await this.ec2.describeInstances().promise();
return result.Reservations return result.Reservations.flatMap(r => r.Instances).filter(reservation => {
.flatMap(r => r.Instances) if (reservation.State.Name !== 'running') return false;
.filter(reservation => { return reservation.Tags.some(t => t.Key === this.tagKey && t.Value === this.tagValue);
if (reservation.State.Name !== 'running') return false; });
return reservation.Tags.some(t => t.Key === this.tagKey && t.Value === this.tagValue);
});
} }
} }
@@ -76,7 +74,6 @@ export async function initConfig(properties) {
} }
export function getConfig(name) { export function getConfig(name) {
if (!awsConfigInit) if (!awsConfigInit) throw new Error("Reading AWS config before it's loaded");
throw new Error("Reading AWS config before it's loaded");
return awsConfig[name] || awsProps(name); return awsConfig[name] || awsProps(name);
} }

View File

@@ -22,5 +22,5 @@
// 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.
export { BuildEnvSetupCeConanDirect } from './ceconan'; export {BuildEnvSetupCeConanDirect} from './ceconan';
export { BuildEnvSetupCliConan } from './cliconan'; export {BuildEnvSetupCliConan} from './cliconan';

View File

@@ -27,7 +27,7 @@ import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import _ from 'underscore'; import _ from 'underscore';
import { logger } from '../logger'; import {logger} from '../logger';
import * as utils from '../utils'; import * as utils from '../utils';
export class BuildEnvSetupBase { export class BuildEnvSetupBase {
@@ -65,7 +65,7 @@ export class BuildEnvSetupBase {
} }
} else if (this.compilerTypeOrGCC === 'gcc') { } else if (this.compilerTypeOrGCC === 'gcc') {
if (this.compiler.exe.includes('/icpx')) { if (this.compiler.exe.includes('/icpx')) {
result = (arch === 'x86') || (arch === 'x86_64'); result = arch === 'x86' || arch === 'x86_64';
} else { } else {
result = await execCompilerCached(this.compiler.exe, ['--target-help']); result = await execCompilerCached(this.compiler.exe, ['--target-help']);
} }
@@ -89,13 +89,12 @@ export class BuildEnvSetupBase {
} }
getCompilerArch() { getCompilerArch() {
let arch = _.find(this.compilerOptionsArr, (option) => { let arch = _.find(this.compilerOptionsArr, option => {
return option.startsWith('-march='); return option.startsWith('-march=');
}); });
let target = _.find(this.compilerOptionsArr, (option) => { let target = _.find(this.compilerOptionsArr, option => {
option.startsWith('-target=') || option.startsWith('-target=') || option.startsWith('--target=');
option.startsWith('--target=');
}); });
if (target) { if (target) {
@@ -130,7 +129,7 @@ export class BuildEnvSetupBase {
if (match) { if (match) {
return match[1]; return match[1];
} else { } else {
const stdlibOption = _.find(key.options, (option) => { const stdlibOption = _.find(key.options, option => {
return option.startsWith('-stdlib='); return option.startsWith('-stdlib=');
}); });
@@ -149,7 +148,7 @@ export class BuildEnvSetupBase {
if (key.options.includes('-m32')) { if (key.options.includes('-m32')) {
return 'x86'; return 'x86';
} else { } else {
let target = _.find(key.options, (option) => { let target = _.find(key.options, option => {
return option.startsWith('-target=') || option.startsWith('--target='); return option.startsWith('-target=') || option.startsWith('--target=');
}); });

View File

@@ -28,9 +28,9 @@ import fs from 'fs-extra';
import _ from 'underscore'; import _ from 'underscore';
import * as exec from '../exec'; import * as exec from '../exec';
import { logger } from '../logger'; import {logger} from '../logger';
import { BuildEnvSetupBase } from './base'; import {BuildEnvSetupBase} from './base';
export class BuildEnvSetupCliConan extends BuildEnvSetupBase { export class BuildEnvSetupCliConan extends BuildEnvSetupBase {
static get key() { static get key() {
@@ -53,11 +53,11 @@ export class BuildEnvSetupCliConan extends BuildEnvSetupBase {
} }
hasBinariesToLink(details) { hasBinariesToLink(details) {
return (details.libpath.length === 0) && (details.staticliblink.length > 0); return details.libpath.length === 0 && details.staticliblink.length > 0;
} }
hasAtLeastOneBinaryToLink(libraryDetails) { hasAtLeastOneBinaryToLink(libraryDetails) {
return _.some(libraryDetails, (details) => this.hasBinariesToLink(details)); return _.some(libraryDetails, details => this.hasBinariesToLink(details));
} }
async prepareConanRequest(libraryDetails, dirPath) { async prepareConanRequest(libraryDetails, dirPath) {
@@ -69,6 +69,7 @@ export class BuildEnvSetupCliConan extends BuildEnvSetupBase {
} }
}); });
// prettier-ignore
data += data +=
'[imports]\n' + '[imports]\n' +
'lib, *.a -> .\n' + 'lib, *.a -> .\n' +
@@ -85,6 +86,7 @@ export class BuildEnvSetupCliConan extends BuildEnvSetupBase {
const args = ['install', '.']; const args = ['install', '.'];
if (this.remote) args.push('-r', this.remote); if (this.remote) args.push('-r', this.remote);
// prettier-ignore
args.push( args.push(
'-s', 'os=Linux', '-s', 'os=Linux',
'-s', 'build_type=Debug', '-s', 'build_type=Debug',
@@ -93,7 +95,8 @@ export class BuildEnvSetupCliConan extends BuildEnvSetupBase {
'-s', `compiler.libcxx=${libcxx}`, '-s', `compiler.libcxx=${libcxx}`,
'-s', `arch=${arch}`, '-s', `arch=${arch}`,
'-s', `stdver=${stdver}`, '-s', `stdver=${stdver}`,
'-s', `flagcollection=${flagcollection}`); '-s', `flagcollection=${flagcollection}`,
);
logger.info('Conan install: ', args); logger.info('Conan install: ', args);
return exec.execute(this.exe, args, {customCwd: dirPath}); return exec.execute(this.exe, args, {customCwd: dirPath});

View File

@@ -22,11 +22,11 @@
// 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.
import { makeKeyedTypeGetter } from '../keyed-type'; import {makeKeyedTypeGetter} from '../keyed-type';
import * as all from './_all'; import * as all from './_all';
export { BuildEnvSetupBase } from './base'; export {BuildEnvSetupBase} from './base';
export * from './_all'; export * from './_all';
export const getBuildEnvTypeByKey = makeKeyedTypeGetter('buildenv', all); export const getBuildEnvTypeByKey = makeKeyedTypeGetter('buildenv', all);

View File

@@ -24,7 +24,7 @@
import _ from 'underscore'; import _ from 'underscore';
import { logger } from './logger'; import {logger} from './logger';
import * as utils from './utils'; import * as utils from './utils';
const InstructionType_jmp = 0; const InstructionType_jmp = 0;
@@ -72,10 +72,7 @@ const gcc = {
filterData: asmArr => { filterData: asmArr => {
const jmpLabelRegex = /\.L\d+:/; const jmpLabelRegex = /\.L\d+:/;
const isCode = x => x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || isFunctionName(x)); const isCode = x => x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || isFunctionName(x));
return _.chain(filterTextSection(asmArr)) return _.chain(filterTextSection(asmArr)).map(_.clone).filter(isCode).value();
.map(_.clone)
.filter(isCode)
.value();
}, },
isFunctionEnd: x => x[0] !== ' ' && x[0] !== '.' && x.includes(':'), isFunctionEnd: x => x[0] !== ' ' && x[0] !== '.' && x.includes(':'),
@@ -101,18 +98,12 @@ const clang = {
const removeComments = x => { const removeComments = x => {
const pos_x86 = x.text.indexOf('# '); const pos_x86 = x.text.indexOf('# ');
const pos_arm = x.text.indexOf('// '); const pos_arm = x.text.indexOf('// ');
if (pos_x86 !== -1) if (pos_x86 !== -1) x.text = utils.trimRight(x.text.substring(0, pos_x86));
x.text = utils.trimRight(x.text.substring(0, pos_x86)); if (pos_arm !== -1) x.text = utils.trimRight(x.text.substring(0, pos_arm));
if (pos_arm !== -1)
x.text = utils.trimRight(x.text.substring(0, pos_arm));
return x; return x;
}; };
return _.chain(filterTextSection(asmArr)) return _.chain(filterTextSection(asmArr)).map(_.clone).filter(isCode).map(removeComments).value();
.map(_.clone)
.filter(isCode)
.map(removeComments)
.value();
}, },
isFunctionEnd: x => x[0] !== ' ' && x[0] !== '.' && x.includes(':'), isFunctionEnd: x => x[0] !== ' ' && x[0] !== '.' && x.includes(':'),
@@ -190,11 +181,13 @@ function splitToCanonicalBasicBlock(basicBlock) {
} }
if (actPosSz === 0) if (actPosSz === 0)
return [{ return [
nameId: basicBlock.nameId, {
start: basicBlock.start, nameId: basicBlock.nameId,
end: basicBlock.end, start: basicBlock.start,
}]; end: basicBlock.end,
},
];
else if (actPosSz === 1) else if (actPosSz === 1)
return [ return [
{nameId: basicBlock.nameId, start: basicBlock.start, end: actionPos[0] + 1}, {nameId: basicBlock.nameId, start: basicBlock.start, end: actionPos[0] + 1},
@@ -219,7 +212,6 @@ function splitToCanonicalBasicBlock(basicBlock) {
result.push(_.clone(tmp)); result.push(_.clone(tmp));
return result; return result;
} }
} }
@@ -260,8 +252,7 @@ function makeEdges(asmArr, arrOfCanonicalBasicBlock, rules) {
const generateName = function (name, suffix) { const generateName = function (name, suffix) {
const pos = name.indexOf('@'); const pos = name.indexOf('@');
if (pos === -1) if (pos === -1) return name + '@' + suffix;
return name + '@' + suffix;
return name.substring(0, pos + 1) + suffix; return name.substring(0, pos + 1) + suffix;
}; };
@@ -312,12 +303,14 @@ function makeEdges(asmArr, arrOfCanonicalBasicBlock, rules) {
} }
function isLLVMBased(compilerType, version) { function isLLVMBased(compilerType, version) {
return version.includes('clang') || return (
version.includes('clang') ||
version.includes('LLVM') || version.includes('LLVM') ||
version.includes('rustc') || version.includes('rustc') ||
compilerType === 'swift' || compilerType === 'swift' ||
compilerType === 'zig' || compilerType === 'zig' ||
compilerType === 'ispc'; compilerType === 'ispc'
);
} }
export function generateStructure(compilerType, version, asmArr) { export function generateStructure(compilerType, version, asmArr) {
@@ -328,19 +321,25 @@ export function generateStructure(compilerType, version, asmArr) {
return funcs; return funcs;
} }
const result = {}; const result = {};
_.each(funcs, _.bind(function (rng) { _.each(
const basicBlocks = splitToBasicBlocks(code, rng, rules.isBasicBlockEnd, rules.isJmpInstruction); funcs,
let arrOfCanonicalBasicBlock = []; _.bind(function (rng) {
_.each(basicBlocks, _.bind(function (elm) { const basicBlocks = splitToBasicBlocks(code, rng, rules.isBasicBlockEnd, rules.isJmpInstruction);
const tmp = splitToCanonicalBasicBlock(elm); let arrOfCanonicalBasicBlock = [];
arrOfCanonicalBasicBlock = arrOfCanonicalBasicBlock.concat(tmp); _.each(
}, this)); basicBlocks,
_.bind(function (elm) {
const tmp = splitToCanonicalBasicBlock(elm);
arrOfCanonicalBasicBlock = arrOfCanonicalBasicBlock.concat(tmp);
}, this),
);
result[code[rng.start].text] = { result[code[rng.start].text] = {
nodes: makeNodes(code, arrOfCanonicalBasicBlock), nodes: makeNodes(code, arrOfCanonicalBasicBlock),
edges: makeEdges(code, arrOfCanonicalBasicBlock, rules), edges: makeEdges(code, arrOfCanonicalBasicBlock, rules),
}; };
}, this)); }, this),
);
return result; return result;
} }

View File

@@ -118,20 +118,14 @@ export class ClientStateExecutor {
} }
fromJsonData(jsondata) { fromJsonData(jsondata) {
if (typeof jsondata.compilerVisible !== 'undefined') if (typeof jsondata.compilerVisible !== 'undefined') this.compilerVisible = jsondata.compilerVisible;
this.compilerVisible = jsondata.compilerVisible;
if (typeof jsondata.compilerOutputVisible !== 'undefined') if (typeof jsondata.compilerOutputVisible !== 'undefined')
this.compilerOutputVisible = jsondata.compilerOutputVisible; this.compilerOutputVisible = jsondata.compilerOutputVisible;
if (typeof jsondata.arguments !== 'undefined') if (typeof jsondata.arguments !== 'undefined') this.arguments = jsondata.arguments;
this.arguments = jsondata.arguments; if (typeof jsondata.argumentsVisible !== 'undefined') this.argumentsVisible = jsondata.argumentsVisible;
if (typeof jsondata.argumentsVisible !== 'undefined') if (typeof jsondata.stdin !== 'undefined') this.stdin = jsondata.stdin;
this.argumentsVisible = jsondata.argumentsVisible; if (typeof jsondata.stdinVisible !== 'undefined') this.stdinVisible = jsondata.stdinVisible;
if (typeof jsondata.stdin !== 'undefined') if (typeof jsondata.wrap !== 'undefined') this.wrap = jsondata.wrap;
this.stdin = jsondata.stdin;
if (typeof jsondata.stdinVisible !== 'undefined')
this.stdinVisible = jsondata.stdinVisible;
if (typeof jsondata.wrap !== 'undefined')
this.wrap = jsondata.wrap;
this.compiler = new ClientStateCompiler(jsondata.compiler); this.compiler = new ClientStateCompiler(jsondata.compiler);
} }
@@ -225,7 +219,7 @@ export class ClientStateTree {
this.newFileId = jsondata.newFileId; this.newFileId = jsondata.newFileId;
} }
if (typeof jsondata.compilers !== 'undefined') { if (typeof jsondata.compilers !== 'undefined') {
for (const compilerdata of jsondata.compilers) { for (const compilerdata of jsondata.compilers) {
const compiler = new ClientStateCompiler(compilerdata); const compiler = new ClientStateCompiler(compilerdata);
if (compiler.id) { if (compiler.id) {
@@ -234,7 +228,7 @@ export class ClientStateTree {
} }
} }
if (typeof jsondata.executors !== 'undefined') { if (typeof jsondata.executors !== 'undefined') {
for (const executor of jsondata.executors) { for (const executor of jsondata.executors) {
this.executors.push(new ClientStateExecutor(executor)); this.executors.push(new ClientStateExecutor(executor));
} }

View File

@@ -37,21 +37,17 @@ export class CompilationQueue {
} }
static fromProps(ceProps) { static fromProps(ceProps) {
return new CompilationQueue( return new CompilationQueue(ceProps('maxConcurrentCompiles', 1), ceProps('compilationEnvTimeoutMs'));
ceProps('maxConcurrentCompiles', 1),
ceProps('compilationEnvTimeoutMs'));
} }
enqueue(job) { enqueue(job) {
const enqueueAsyncId = executionAsyncId(); const enqueueAsyncId = executionAsyncId();
// If we're asked to enqueue a job when we're already in a async queued job context, just run it. // If we're asked to enqueue a job when we're already in a async queued job context, just run it.
// This prevents a deadlock. // This prevents a deadlock.
if (this._running.has(enqueueAsyncId)) if (this._running.has(enqueueAsyncId)) return job();
return job();
return this._queue.add(() => { return this._queue.add(() => {
const jobAsyncId = executionAsyncId(); const jobAsyncId = executionAsyncId();
if (this._running.has(jobAsyncId)) if (this._running.has(jobAsyncId)) throw new Error('somehow we entered the context twice');
throw new Error('somehow we entered the context twice');
try { try {
this._running.add(jobAsyncId); this._running.add(jobAsyncId);
return job(); return job();

View File

@@ -22,67 +22,67 @@
// 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.
export { AdaCompiler } from './ada'; export {AdaCompiler} from './ada';
export { AnalysisTool } from './analysis-tool'; export {AnalysisTool} from './analysis-tool';
export { AssemblyCompiler } from './assembly'; export {AssemblyCompiler} from './assembly';
export { NasmCompiler } from './nasm'; export {NasmCompiler} from './nasm';
export { Cc65Compiler } from './cc65'; export {Cc65Compiler} from './cc65';
export { CircleCompiler } from './circle'; export {CircleCompiler} from './circle';
export { ClangCompiler } from './clang'; export {ClangCompiler} from './clang';
export { ClangCudaCompiler } from './clang'; export {ClangCudaCompiler} from './clang';
export { ClangHipCompiler } from './clang'; export {ClangHipCompiler} from './clang';
export { CleanCompiler } from './clean'; export {CleanCompiler} from './clean';
export { CprocCompiler } from './cproc'; export {CprocCompiler} from './cproc';
export { CrystalCompiler } from './crystal'; export {CrystalCompiler} from './crystal';
export { DartCompiler } from './dart'; export {DartCompiler} from './dart';
export { DefaultCompiler } from './default'; export {DefaultCompiler} from './default';
export { DMDCompiler } from './dmd'; export {DMDCompiler} from './dmd';
export { CSharpCompiler } from './dotnet'; export {CSharpCompiler} from './dotnet';
export { EllccCompiler } from './ellcc'; export {EllccCompiler} from './ellcc';
export { ErlangCompiler } from './erlang'; export {ErlangCompiler} from './erlang';
export { EWARMCompiler } from './ewarm'; export {EWARMCompiler} from './ewarm';
export { EWAVRCompiler } from './ewavr'; export {EWAVRCompiler} from './ewavr';
export { FakeCompiler } from './fake-for-test'; export {FakeCompiler} from './fake-for-test';
export { FSharpCompiler } from './dotnet'; export {FSharpCompiler} from './dotnet';
export { FortranCompiler } from './fortran'; export {FortranCompiler} from './fortran';
export { GCCCompiler } from './gcc'; export {GCCCompiler} from './gcc';
export { GCCRSCompiler } from './gccrs'; export {GCCRSCompiler} from './gccrs';
export { GolangCompiler } from './golang'; export {GolangCompiler} from './golang';
export { HaskellCompiler } from './haskell'; export {HaskellCompiler} from './haskell';
export { ISPCCompiler } from './ispc'; export {ISPCCompiler} from './ispc';
export { JavaCompiler } from './java'; export {JavaCompiler} from './java';
export { KotlinCompiler } from './kotlin'; export {KotlinCompiler} from './kotlin';
export { LDCCompiler } from './ldc'; export {LDCCompiler} from './ldc';
export { LLCCompiler } from './llc'; export {LLCCompiler} from './llc';
export { LLVMmcaTool } from './llvm-mca'; export {LLVMmcaTool} from './llvm-mca';
export { NimCompiler } from './nim'; export {NimCompiler} from './nim';
export { NvccCompiler } from './nvcc'; export {NvccCompiler} from './nvcc';
export { OCamlCompiler } from './ocaml'; export {OCamlCompiler} from './ocaml';
export { OptCompiler } from './opt'; export {OptCompiler} from './opt';
export { OSACATool } from './osaca'; export {OSACATool} from './osaca';
export { FPCCompiler } from './pascal'; export {FPCCompiler} from './pascal';
export { PascalWinCompiler } from './pascal-win'; export {PascalWinCompiler} from './pascal-win';
export { PPCICompiler } from './ppci'; export {PPCICompiler} from './ppci';
export { PtxAssembler } from './ptxas'; export {PtxAssembler} from './ptxas';
export { PythonCompiler } from './python'; export {PythonCompiler} from './python';
export { RubyCompiler } from './ruby'; export {RubyCompiler} from './ruby';
export { RustCompiler } from './rust'; export {RustCompiler} from './rust';
export { RustcCgGCCCompiler } from './rustc-cg-gcc'; export {RustcCgGCCCompiler} from './rustc-cg-gcc';
export { MrustcCompiler } from './mrustc'; export {MrustcCompiler} from './mrustc';
export { ScalaCompiler } from './scala'; export {ScalaCompiler} from './scala';
export { SdccCompiler } from './sdcc'; export {SdccCompiler} from './sdcc';
export { SolidityCompiler } from './solidity'; export {SolidityCompiler} from './solidity';
export { SPIRVCompiler } from './spirv'; export {SPIRVCompiler} from './spirv';
export { SwiftCompiler } from './swift'; export {SwiftCompiler} from './swift';
export { TenDRACompiler } from './tendra'; export {TenDRACompiler} from './tendra';
export { TinyCCompiler } from './tinyc'; export {TinyCCompiler} from './tinyc';
export { TypeScriptCompiler } from './typescript'; export {TypeScriptCompiler} from './typescript';
export { VBCompiler } from './dotnet'; export {VBCompiler} from './dotnet';
export { Win32Compiler } from './win32'; export {Win32Compiler} from './win32';
export { Win32VcCompiler } from './win32-vc'; export {Win32VcCompiler} from './win32-vc';
export { Win32Vc6Compiler } from './win32-vc6'; export {Win32Vc6Compiler} from './win32-vc6';
export { WineVcCompiler } from './wine-vc'; export {WineVcCompiler} from './wine-vc';
export { WslVcCompiler } from './wsl-vc'; export {WslVcCompiler} from './wsl-vc';
export { ZigCompiler } from './zig'; export {ZigCompiler} from './zig';
export { ZigCC } from './zigcc'; export {ZigCC} from './zigcc';
export { ZigCXX } from './zigcxx'; export {ZigCXX} from './zigcxx';

View File

@@ -22,16 +22,17 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
// Plain compiler, which just runs the tool and returns whatever the output was // Plain compiler, which just runs the tool and returns whatever the output was
export class AnalysisTool extends BaseCompiler { export class AnalysisTool extends BaseCompiler {
static get key() { return 'analysis-tool'; } static get key() {
return 'analysis-tool';
}
constructor(info, env) { constructor(info, env) {
// Default is to disable all "cosmetic" filters // Default is to disable all "cosmetic" filters
if (!info.disabledFilters) if (!info.disabledFilters) info.disabledFilters = ['labels', 'directives', 'commentOnly', 'trim'];
info.disabledFilters = ['labels', 'directives', 'commentOnly', 'trim'];
super(info, env); super(info, env);
} }

View File

@@ -25,14 +25,16 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { AsmRaw } from '../parsers/asm-raw'; import {AsmRaw} from '../parsers/asm-raw';
import * as utils from '../utils'; import * as utils from '../utils';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
export class AssemblyCompiler extends BaseCompiler { export class AssemblyCompiler extends BaseCompiler {
static get key() { return 'assembly'; } static get key() {
return 'assembly';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
@@ -73,13 +75,18 @@ export class AssemblyCompiler extends BaseCompiler {
async runReadelf(fullResult, objectFilename) { async runReadelf(fullResult, objectFilename) {
let execOptions = this.getDefaultExecOptions(); let execOptions = this.getDefaultExecOptions();
execOptions.customCwd = path.dirname(objectFilename); execOptions.customCwd = path.dirname(objectFilename);
return await this.doBuildstepAndAddToResult(fullResult, 'readelf', this.env.ceProps('readelf'), return await this.doBuildstepAndAddToResult(
['-h', objectFilename], execOptions); fullResult,
'readelf',
this.env.ceProps('readelf'),
['-h', objectFilename],
execOptions,
);
} }
async getArchitecture(fullResult, objectFilename) { async getArchitecture(fullResult, objectFilename) {
const result = await this.runReadelf(fullResult, objectFilename); const result = await this.runReadelf(fullResult, objectFilename);
const output = result.stdout.map((line) => line.text).join('\n'); const output = result.stdout.map(line => line.text).join('\n');
if (output.includes('ELF32') && output.includes('80386')) { if (output.includes('ELF32') && output.includes('80386')) {
return 'x86'; return 'x86';
} else if (output.includes('ELF64') && output.includes('X86-64')) { } else if (output.includes('ELF64') && output.includes('X86-64')) {

View File

@@ -22,10 +22,12 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
export class Cc65Compiler extends BaseCompiler { export class Cc65Compiler extends BaseCompiler {
static get key() { return 'cc65'; } static get key() {
return 'cc65';
}
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
return ['-g', '-o', this.filename(outputFilename)]; return ['-g', '-o', this.filename(outputFilename)];

View File

@@ -24,10 +24,12 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
export class CircleCompiler extends BaseCompiler { export class CircleCompiler extends BaseCompiler {
static get key() { return 'circle'; } static get key() {
return 'circle';
}
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
let options = [`-o=${this.filename(outputFilename)}`]; let options = [`-o=${this.filename(outputFilename)}`];

View File

@@ -24,7 +24,7 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
export class CprocCompiler extends BaseCompiler { export class CprocCompiler extends BaseCompiler {
static get key() { static get key() {

View File

@@ -26,13 +26,15 @@ import path from 'path';
import _ from 'underscore'; import _ from 'underscore';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { CrystalAsmParser } from '../parsers/asm-parser-crystal'; import {CrystalAsmParser} from '../parsers/asm-parser-crystal';
import { CrystalParser } from './argument-parsers'; import {CrystalParser} from './argument-parsers';
export class CrystalCompiler extends BaseCompiler { export class CrystalCompiler extends BaseCompiler {
static get key() { return 'crystal'; } static get key() {
return 'crystal';
}
constructor(compiler, env) { constructor(compiler, env) {
super(compiler, env); super(compiler, env);

View File

@@ -24,11 +24,11 @@
import Semver from 'semver'; import Semver from 'semver';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { DartAsmParser } from '../parsers/asm-parser-dart'; import {DartAsmParser} from '../parsers/asm-parser-dart';
import * as utils from '../utils'; import * as utils from '../utils';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
export class DartCompiler extends BaseCompiler { export class DartCompiler extends BaseCompiler {
constructor(info, env) { constructor(info, env) {
@@ -36,7 +36,9 @@ export class DartCompiler extends BaseCompiler {
this.asm = new DartAsmParser(); this.asm = new DartAsmParser();
} }
static get key() { return 'dart'; } static get key() {
return 'dart';
}
prepareArguments(userOptions, filters, backendOptions, inputFilename, outputFilename, libraries) { prepareArguments(userOptions, filters, backendOptions, inputFilename, outputFilename, libraries) {
let options = this.optionsForFilter(filters, outputFilename, userOptions); let options = this.optionsForFilter(filters, outputFilename, userOptions);
@@ -61,15 +63,9 @@ export class DartCompiler extends BaseCompiler {
const dartCompileIntroduction = '2.10.0'; const dartCompileIntroduction = '2.10.0';
if (Semver.lt(utils.asSafeVer(this.compiler.semver), dartCompileIntroduction, true)) { if (Semver.lt(utils.asSafeVer(this.compiler.semver), dartCompileIntroduction, true)) {
return [ return ['-k', 'aot', '-o', this.filename(outputFilename)];
'-k', 'aot',
'-o', this.filename(outputFilename),
];
} else { } else {
return [ return ['compile', 'aot-snapshot', '-o', this.filename(outputFilename)];
'compile', 'aot-snapshot',
'-o', this.filename(outputFilename),
];
} }
} }

View File

@@ -22,8 +22,10 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
export class DefaultCompiler extends BaseCompiler { export class DefaultCompiler extends BaseCompiler {
static get key() { return 'default'; } static get key() {
return 'default';
}
} }

View File

@@ -24,12 +24,14 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
export class DMDCompiler extends BaseCompiler { export class DMDCompiler extends BaseCompiler {
static get key() { return 'dmd'; } static get key() {
return 'dmd';
}
constructor(compiler, env) { constructor(compiler, env) {
super(compiler, env); super(compiler, env);
@@ -49,7 +51,8 @@ export class DMDCompiler extends BaseCompiler {
const lPath = path.basename(outputFilename); const lPath = path.basename(outputFilename);
return this.handlePostProcessResult( return this.handlePostProcessResult(
result, result,
await this.exec(postProcesses[0], ['-l', lPath], {customCwd: dirPath, maxOutput: maxSize})); await this.exec(postProcesses[0], ['-l', lPath], {customCwd: dirPath, maxOutput: maxSize}),
);
} }
getOutputFilename(dirPath, outputFilebase) { getOutputFilename(dirPath, outputFilebase) {
@@ -57,7 +60,7 @@ export class DMDCompiler extends BaseCompiler {
} }
buildExecutable(compiler, options, inputFilename, execOptions) { buildExecutable(compiler, options, inputFilename, execOptions) {
options = options.filter((param) => param !== '-c'); options = options.filter(param => param !== '-c');
return this.runCompiler(compiler, options, inputFilename, execOptions); return this.runCompiler(compiler, options, inputFilename, execOptions);
} }

View File

@@ -22,10 +22,12 @@
// 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.
import { ClangCompiler } from './clang'; import {ClangCompiler} from './clang';
export class EllccCompiler extends ClangCompiler { export class EllccCompiler extends ClangCompiler {
static get key() { return 'ellcc'; } static get key() {
return 'ellcc';
}
getSharedLibraryPathsAsArguments() { getSharedLibraryPathsAsArguments() {
const pathFlag = this.compiler.rpathFlag || '-Wl,-rpath,'; const pathFlag = this.compiler.rpathFlag || '-Wl,-rpath,';

View File

@@ -24,12 +24,14 @@
import temp from 'temp'; import temp from 'temp';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { AsmEWAVRParser } from '../parsers/asm-parser-ewavr'; import {AsmEWAVRParser} from '../parsers/asm-parser-ewavr';
export class EWARMCompiler extends BaseCompiler { export class EWARMCompiler extends BaseCompiler {
static get key() { return 'ewarm'; } static get key() {
return 'ewarm';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
this.asm = new AsmEWAVRParser(this.compilerProps); this.asm = new AsmEWAVRParser(this.compilerProps);
@@ -38,10 +40,8 @@ export class EWARMCompiler extends BaseCompiler {
newTempDir() { newTempDir() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
temp.mkdir({prefix: 'compiler-explorer-compiler', dir: process.env.TMP}, (err, dirPath) => { temp.mkdir({prefix: 'compiler-explorer-compiler', dir: process.env.TMP}, (err, dirPath) => {
if (err) if (err) reject(`Unable to open temp file: ${err}`);
reject(`Unable to open temp file: ${err}`); else resolve(dirPath);
else
resolve(dirPath);
}); });
}); });
} }
@@ -50,10 +50,7 @@ export class EWARMCompiler extends BaseCompiler {
if (filters.binary) { if (filters.binary) {
return []; return [];
} }
return [ return ['-lB', this.filename(outputFilename), '-o', this.filename(outputFilename + '.obj')];
'-lB', this.filename(outputFilename),
'-o', this.filename(outputFilename + '.obj'),
];
} }
} }

View File

@@ -24,11 +24,13 @@
import temp from 'temp'; import temp from 'temp';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { AsmEWAVRParser } from '../parsers/asm-parser-ewavr'; import {AsmEWAVRParser} from '../parsers/asm-parser-ewavr';
export class EWAVRCompiler extends BaseCompiler { export class EWAVRCompiler extends BaseCompiler {
static get key() { return 'ewavr'; } static get key() {
return 'ewavr';
}
constructor(info, env) { constructor(info, env) {
info.supportsDemangle = false; info.supportsDemangle = false;
@@ -40,10 +42,8 @@ export class EWAVRCompiler extends BaseCompiler {
newTempDir() { newTempDir() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
temp.mkdir({prefix: 'compiler-explorer-compiler', dir: process.env.TMP}, (err, dirPath) => { temp.mkdir({prefix: 'compiler-explorer-compiler', dir: process.env.TMP}, (err, dirPath) => {
if (err) if (err) reject(`Unable to open temp file: ${err}`);
reject(`Unable to open temp file: ${err}`); else resolve(dirPath);
else
resolve(dirPath);
}); });
}); });
} }
@@ -52,10 +52,7 @@ export class EWAVRCompiler extends BaseCompiler {
if (filters.binary) { if (filters.binary) {
return []; return [];
} }
return [ return ['-lB', this.filename(outputFilename), '-o', this.filename(outputFilename + '.obj')];
'-lB', this.filename(outputFilename),
'-o', this.filename(outputFilename + '.obj'),
];
} }
} }

View File

@@ -30,11 +30,14 @@ export class FakeCompiler {
} }
constructor(info) { constructor(info) {
this.compiler = Object.assign({ this.compiler = Object.assign(
id: 'fake-for-test', {
lang: 'fake-lang', id: 'fake-for-test',
options: '', lang: 'fake-lang',
}, info); options: '',
},
info,
);
this.lang = {id: this.compiler.lang, name: `Language ${this.compiler.lang}`}; this.lang = {id: this.compiler.lang, name: `Language ${this.compiler.lang}`};
this.info = info; this.info = info;
} }
@@ -67,12 +70,14 @@ export class FakeCompiler {
} }
cmake(files, options) { cmake(files, options) {
return Promise.resolve(_.extend(this.info.fakeResult || {}, { return Promise.resolve(
input: { _.extend(this.info.fakeResult || {}, {
files: files, input: {
options: options, files: files,
}, options: options,
})); },
}),
);
} }
initalize() { initalize() {

View File

@@ -24,11 +24,13 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import * as utils from '../utils'; import * as utils from '../utils';
export class FortranCompiler extends BaseCompiler { export class FortranCompiler extends BaseCompiler {
static get key() { return 'fortran'; } static get key() {
return 'fortran';
}
async runCompiler(compiler, options, inputFilename, execOptions) { async runCompiler(compiler, options, inputFilename, execOptions) {
if (!execOptions) { if (!execOptions) {

View File

@@ -22,8 +22,10 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
export class GCCCompiler extends BaseCompiler { export class GCCCompiler extends BaseCompiler {
static get key() { return 'gcc'; } static get key() {
return 'gcc';
}
} }

View File

@@ -22,8 +22,10 @@
// 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.
import { GCCCompiler } from './gcc'; import {GCCCompiler} from './gcc';
export class GCCRSCompiler extends GCCCompiler { export class GCCRSCompiler extends GCCCompiler {
static get key() { return 'gccrs'; } static get key() {
return 'gccrs';
}
} }

View File

@@ -24,10 +24,10 @@
import _ from 'underscore'; import _ from 'underscore';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import * as utils from '../utils'; import * as utils from '../utils';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
// Each arch has a list of jump instructions in // Each arch has a list of jump instructions in
// Go source src/cmd/asm/internal/arch. // Go source src/cmd/asm/internal/arch.
@@ -170,7 +170,8 @@ export class GolangCompiler extends BaseCompiler {
extractLogging(stdout) { extractLogging(stdout) {
let filepath = `./${this.compileFilename}`; let filepath = `./${this.compileFilename}`;
const reLogging = /^[^:]+:\d+:(\d+:)?\s.*/; const reLogging = /^[^:]+:\d+:(\d+:)?\s.*/;
return stdout.filter(obj => obj.text.match(reLogging)) return stdout
.filter(obj => obj.text.match(reLogging))
.map(obj => obj.text.replace(filepath, '<source>')) .map(obj => obj.text.replace(filepath, '<source>'))
.join('\n'); .join('\n');
} }

View File

@@ -22,7 +22,7 @@
// 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.
import { makeKeyedTypeGetter } from '../keyed-type'; import {makeKeyedTypeGetter} from '../keyed-type';
import * as all from './_all'; import * as all from './_all';

View File

@@ -22,12 +22,14 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { ISPCParser } from './argument-parsers'; import {ISPCParser} from './argument-parsers';
export class ISPCCompiler extends BaseCompiler { export class ISPCCompiler extends BaseCompiler {
static get key() { return 'ispc'; } static get key() {
return 'ispc';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);

View File

@@ -22,8 +22,8 @@
// 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.
import { KotlinParser } from './argument-parsers'; import {KotlinParser} from './argument-parsers';
import { JavaCompiler } from './java'; import {JavaCompiler} from './java';
export class KotlinCompiler extends JavaCompiler { export class KotlinCompiler extends JavaCompiler {
static get key() { static get key() {
@@ -50,8 +50,9 @@ export class KotlinCompiler extends JavaCompiler {
filterUserOptions(userOptions) { filterUserOptions(userOptions) {
// filter options without extra arguments // filter options without extra arguments
userOptions = (userOptions || []).filter(option => userOptions = (userOptions || []).filter(
option !== '-script' && option !== '-progressive' && !option.startsWith('-Xjavac')); option => option !== '-script' && option !== '-progressive' && !option.startsWith('-Xjavac'),
);
const oneArgForbiddenList = new Set([ const oneArgForbiddenList = new Set([
// -jdk-home path // -jdk-home path
@@ -72,9 +73,7 @@ export class KotlinCompiler extends JavaCompiler {
// Forcibly enable javap // Forcibly enable javap
filters.binary = true; filters.binary = true;
return [ return ['-Xjavac-arguments="-Xlint:all"'];
'-Xjavac-arguments="-Xlint:all"',
];
} }
/** /**

View File

@@ -27,13 +27,15 @@ import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import semverParser from 'semver'; import semverParser from 'semver';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { logger } from '../logger'; import {logger} from '../logger';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
export class LDCCompiler extends BaseCompiler { export class LDCCompiler extends BaseCompiler {
static get key() { return 'ldc'; } static get key() {
return 'ldc';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
@@ -76,7 +78,8 @@ export class LDCCompiler extends BaseCompiler {
const newOptions = options.concat('-vcg-ast'); const newOptions = options.concat('-vcg-ast');
const execOptions = this.getDefaultExecOptions(); const execOptions = this.getDefaultExecOptions();
return this.loadASTOutput( return this.loadASTOutput(
await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions)); await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions),
);
} }
async loadASTOutput(output) { async loadASTOutput(output) {
@@ -99,7 +102,6 @@ export class LDCCompiler extends BaseCompiler {
// Override the IR file name method for LDC because the output file is different from clang. // Override the IR file name method for LDC because the output file is different from clang.
getIrOutputFilename(inputFilename) { getIrOutputFilename(inputFilename) {
return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase) return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase).replace('.s', '.ll');
.replace('.s', '.ll');
} }
} }

View File

@@ -22,12 +22,14 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
export class LLCCompiler extends BaseCompiler { export class LLCCompiler extends BaseCompiler {
static get key() { return 'llc'; } static get key() {
return 'llc';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);

View File

@@ -22,14 +22,18 @@
// 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.
import { AnalysisTool } from './analysis-tool'; import {AnalysisTool} from './analysis-tool';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
// Plain compiler, which just runs the tool and returns whatever the output was // Plain compiler, which just runs the tool and returns whatever the output was
export class LLVMmcaTool extends AnalysisTool { export class LLVMmcaTool extends AnalysisTool {
static get key() { return 'llvm-mca'; } static get key() {
return 'llvm-mca';
}
supportsObjdump() { return false; } supportsObjdump() {
return false;
}
getOutputFilenameArgs(filename) { getOutputFilenameArgs(filename) {
// TODO: Some tools might require an argument of the form -arg=filename // TODO: Some tools might require an argument of the form -arg=filename

View File

@@ -24,24 +24,34 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { MrustcParser } from './argument-parsers'; import {MrustcParser} from './argument-parsers';
export class MrustcCompiler extends BaseCompiler { export class MrustcCompiler extends BaseCompiler {
static get key() { return 'mrustc'; } static get key() {
return 'mrustc';
}
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
// mrustc always dumps the C code for <baseout> target in the <baseout>.c file. // mrustc always dumps the C code for <baseout> target in the <baseout>.c file.
// In our case, the actual file in -o is not even created because we are // In our case, the actual file in -o is not even created because we are
// faking the last step (C compilation). // faking the last step (C compilation).
// Craft the 'outname' to have the intermediate .c file writen in outputFilename. // Craft the 'outname' to have the intermediate .c file writen in outputFilename.
let outname = path.join(path.dirname(this.filename(outputFilename)), let outname = path.join(
path.basename(this.filename(outputFilename), '.c')); path.dirname(this.filename(outputFilename)),
path.basename(this.filename(outputFilename), '.c'),
);
// Currently always targets a rlib, no binary support at the moment. // Currently always targets a rlib, no binary support at the moment.
return ['--crate-type', 'rlib', return [
'-o', outname, '-L', path.join(path.dirname(this.compiler.exe), '..', 'output')]; '--crate-type',
'rlib',
'-o',
outname,
'-L',
path.join(path.dirname(this.compiler.exe), '..', 'output'),
];
} }
async runCompiler(compiler, options, inputFilename, execOptions) { async runCompiler(compiler, options, inputFilename, execOptions) {
@@ -59,5 +69,4 @@ export class MrustcCompiler extends BaseCompiler {
getArgumentParser() { getArgumentParser() {
return MrustcParser; return MrustcParser;
} }
} }

View File

@@ -26,14 +26,22 @@ import path from 'path';
import * as utils from '../utils'; import * as utils from '../utils';
import { AssemblyCompiler } from './assembly'; import {AssemblyCompiler} from './assembly';
export class NasmCompiler extends AssemblyCompiler { export class NasmCompiler extends AssemblyCompiler {
static get key() { return 'nasm'; } static get key() {
return 'nasm';
}
prepareArguments(userOptions, filters, backendOptions, inputFilename, outputFilename, libraries) { prepareArguments(userOptions, filters, backendOptions, inputFilename, outputFilename, libraries) {
let options = super.prepareArguments(userOptions, filters, backendOptions, inputFilename, let options = super.prepareArguments(
outputFilename, libraries); userOptions,
filters,
backendOptions,
inputFilename,
outputFilename,
libraries,
);
let fmode; let fmode;
if (options.includes('-felf')) { if (options.includes('-felf')) {
@@ -44,11 +52,11 @@ export class NasmCompiler extends AssemblyCompiler {
fmode = 'bin'; fmode = 'bin';
} else if (options.includes('-f')) { } else if (options.includes('-f')) {
const idx = options.indexOf('-f'); const idx = options.indexOf('-f');
fmode = options[idx+1]; fmode = options[idx + 1];
} }
if (!fmode) { if (!fmode) {
options = ['-g','-f','elf','-F','stabs'].concat(options); options = ['-g', '-f', 'elf', '-F', 'stabs'].concat(options);
} }
return options; return options;

View File

@@ -24,13 +24,15 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { SassAsmParser } from '../parsers/asm-parser-sass'; import {SassAsmParser} from '../parsers/asm-parser-sass';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
export class NvccCompiler extends BaseCompiler { export class NvccCompiler extends BaseCompiler {
static get key() { return 'nvcc'; } static get key() {
return 'nvcc';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);

View File

@@ -22,12 +22,14 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { PascalParser } from './argument-parsers'; import {PascalParser} from './argument-parsers';
export class OCamlCompiler extends BaseCompiler { export class OCamlCompiler extends BaseCompiler {
static get key() { return 'ocaml'; } static get key() {
return 'ocaml';
}
constructor(compilerInfo, env) { constructor(compilerInfo, env) {
super(compilerInfo, env); super(compilerInfo, env);

View File

@@ -22,12 +22,14 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { ClangParser } from './argument-parsers'; import {ClangParser} from './argument-parsers';
export class OptCompiler extends BaseCompiler { export class OptCompiler extends BaseCompiler {
static get key() { return 'opt'; } static get key() {
return 'opt';
}
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
return ['-o', this.filename(outputFilename), '-S']; return ['-o', this.filename(outputFilename), '-S'];

View File

@@ -22,14 +22,18 @@
// 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.
import { AnalysisTool } from './analysis-tool'; import {AnalysisTool} from './analysis-tool';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
// Plain compiler, which just runs the tool and returns whatever the output was // Plain compiler, which just runs the tool and returns whatever the output was
export class OSACATool extends AnalysisTool { export class OSACATool extends AnalysisTool {
static get key() { return 'osaca'; } static get key() {
return 'osaca';
}
supportsObjdump() { return false; } supportsObjdump() {
return false;
}
getOutputFilenameArgs(filename) { getOutputFilenameArgs(filename) {
return ['-o', filename]; return ['-o', filename];
@@ -38,7 +42,7 @@ export class OSACATool extends AnalysisTool {
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
return this.getOutputFilenameArgs(outputFilename); return this.getOutputFilenameArgs(outputFilename);
} }
getDefaultFilters() { getDefaultFilters() {
// Disable everything, also intel syntax // Disable everything, also intel syntax
return { return {

View File

@@ -26,15 +26,17 @@ import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { MapFileReaderDelphi } from '../mapfiles/map-file-delphi'; import {MapFileReaderDelphi} from '../mapfiles/map-file-delphi';
import { PELabelReconstructor } from '../pe32-support'; import {PELabelReconstructor} from '../pe32-support';
import * as utils from '../utils'; import * as utils from '../utils';
import { PascalUtils } from './pascal-utils'; import {PascalUtils} from './pascal-utils';
export class PascalWinCompiler extends BaseCompiler { export class PascalWinCompiler extends BaseCompiler {
static get key() { return 'pascal-win'; } static get key() {
return 'pascal-win';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
@@ -91,24 +93,26 @@ export class PascalWinCompiler extends BaseCompiler {
let args = ['-d', outputFilename]; let args = ['-d', outputFilename];
if (intelAsm) args = args.concat(['-M', 'intel']); if (intelAsm) args = args.concat(['-M', 'intel']);
return this.exec(this.compiler.objdumper, args, {maxOutput: 1024 * 1024 * 1024}) return this.exec(this.compiler.objdumper, args, {maxOutput: 1024 * 1024 * 1024}).then(objResult => {
.then((objResult) => { if (objResult.code !== 0) {
if (objResult.code !== 0) { result.asm = '<No output: objdump returned ' + objResult.code + '>';
result.asm = '<No output: objdump returned ' + objResult.code + '>'; } else {
} else { result.asm = objResult.stdout;
result.asm = objResult.stdout; }
}
return result; return result;
}); });
} }
async saveDummyProjectFile(filename, unitName, unitPath) { async saveDummyProjectFile(filename, unitName, unitPath) {
await fs.writeFile(filename, await fs.writeFile(
filename,
// prettier-ignore
'program prog;\n' + 'program prog;\n' +
'uses ' + unitName + ' in \'' + unitPath + '\';\n' + 'uses ' + unitName + ' in \'' + unitPath + '\';\n' +
'begin\n' + 'begin\n' +
'end.\n'); 'end.\n',
);
} }
async writeAllFiles(dirPath, source, files, filters) { async writeAllFiles(dirPath, source, files, filters) {
@@ -159,19 +163,12 @@ export class PascalWinCompiler extends BaseCompiler {
options.pop(); options.pop();
options.unshift( options.unshift('-CC', '-W', '-H', '-GD', '-$D+', '-V', '-B');
'-CC',
'-W',
'-H',
'-GD',
'-$D+',
'-V',
'-B');
options.push(projectFile); options.push(projectFile);
execOptions.customCwd = tempPath; execOptions.customCwd = tempPath;
return this.exec(compiler, options, execOptions).then((result) => { return this.exec(compiler, options, execOptions).then(result => {
result.inputFilename = inputFilename; result.inputFilename = inputFilename;
result.stdout = utils.parseOutput(result.stdout, inputFilename); result.stdout = utils.parseOutput(result.stdout, inputFilename);
result.stderr = utils.parseOutput(result.stderr, inputFilename); result.stderr = utils.parseOutput(result.stderr, inputFilename);
@@ -182,11 +179,11 @@ export class PascalWinCompiler extends BaseCompiler {
optionsForFilter(filters) { optionsForFilter(filters) {
filters.binary = true; filters.binary = true;
filters.dontMaskFilenames = true; filters.dontMaskFilenames = true;
filters.preProcessBinaryAsmLines = (asmLines) => { filters.preProcessBinaryAsmLines = asmLines => {
const mapFileReader = new MapFileReaderDelphi(this.mapFilename); const mapFileReader = new MapFileReaderDelphi(this.mapFilename);
const reconstructor = new PELabelReconstructor(asmLines, false, mapFileReader, false); const reconstructor = new PELabelReconstructor(asmLines, false, mapFileReader, false);
reconstructor.run('output'); reconstructor.run('output');
return reconstructor.asmLines; return reconstructor.asmLines;
}; };

View File

@@ -27,11 +27,11 @@ import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import _ from 'underscore'; import _ from 'underscore';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import * as utils from '../utils'; import * as utils from '../utils';
import { PascalParser } from './argument-parsers'; import {PascalParser} from './argument-parsers';
import { PascalUtils } from './pascal-utils'; import {PascalUtils} from './pascal-utils';
export class FPCCompiler extends BaseCompiler { export class FPCCompiler extends BaseCompiler {
static get key() { static get key() {
@@ -113,12 +113,9 @@ export class FPCCompiler extends BaseCompiler {
const lastLinefeedBeforeStart = input.lastIndexOf('\n', relevantAsmStartsAt); const lastLinefeedBeforeStart = input.lastIndexOf('\n', relevantAsmStartsAt);
if (lastLinefeedBeforeStart !== -1) { if (lastLinefeedBeforeStart !== -1) {
input = input =
input.substr(0, input.indexOf('00000000004')) + '\n' + input.substr(0, input.indexOf('00000000004')) + '\n' + input.substr(lastLinefeedBeforeStart + 1);
input.substr(lastLinefeedBeforeStart + 1);
} else { } else {
input = input = input.substr(0, input.indexOf('00000000004')) + '\n' + input.substr(relevantAsmStartsAt);
input.substr(0, input.indexOf('00000000004')) + '\n' +
input.substr(relevantAsmStartsAt);
} }
} }
return input; return input;
@@ -129,11 +126,14 @@ export class FPCCompiler extends BaseCompiler {
} }
async saveDummyProjectFile(filename, unitName, unitPath) { async saveDummyProjectFile(filename, unitName, unitPath) {
await fs.writeFile(filename, await fs.writeFile(
filename,
// prettier-ignore
'program prog;\n' + 'program prog;\n' +
'uses ' + unitName + ' in \'' + unitPath + '\';\n' + 'uses ' + unitName + ' in \'' + unitPath + '\';\n' +
'begin\n' + 'begin\n' +
'end.\n'); 'end.\n',
);
} }
async writeAllFiles(dirPath, source, files, filters) { async writeAllFiles(dirPath, source, files, filters) {

View File

@@ -22,21 +22,19 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import * as exec from '../exec'; import * as exec from '../exec';
import { logger } from '../logger'; import {logger} from '../logger';
const forbiddenOptions = new Set([ const forbiddenOptions = new Set(['--report', '--text-report', '--html-report']);
'--report',
'--text-report',
'--html-report',
]);
export class PPCICompiler extends BaseCompiler { export class PPCICompiler extends BaseCompiler {
static get key() { return 'ppci'; } static get key() {
return 'ppci';
}
filterUserOptions(args) { filterUserOptions(args) {
return args.filter((item) => { return args.filter(item => {
if (typeof item !== 'string') return true; if (typeof item !== 'string') return true;
return !forbiddenOptions.has(item.toLowerCase()); return !forbiddenOptions.has(item.toLowerCase());

View File

@@ -24,11 +24,11 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { SassAsmParser } from '../parsers/asm-parser-sass'; import {SassAsmParser} from '../parsers/asm-parser-sass';
import * as utils from '../utils'; import * as utils from '../utils';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
export class PtxAssembler extends BaseCompiler { export class PtxAssembler extends BaseCompiler {
static get key() { static get key() {
@@ -111,8 +111,7 @@ export class PtxAssembler extends BaseCompiler {
async objdump(outputFilename, result, maxSize) { async objdump(outputFilename, result, maxSize) {
const dirPath = path.dirname(outputFilename); const dirPath = path.dirname(outputFilename);
let args = ['-c', '-g', '-hex', outputFilename]; let args = ['-c', '-g', '-hex', outputFilename];
const objResult = await this.exec( const objResult = await this.exec(this.compiler.objdumper, args, {maxOutput: maxSize, customCwd: dirPath});
this.compiler.objdumper, args, {maxOutput: maxSize, customCwd: dirPath});
result.asm = objResult.stdout; result.asm = objResult.stdout;
if (objResult.code !== 0) { if (objResult.code !== 0) {
result.asm = '<No output: objdump returned ' + objResult.code + '>'; result.asm = '<No output: objdump returned ' + objResult.code + '>';

View File

@@ -22,13 +22,15 @@
// 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.
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { resolvePathFromAppRoot } from '../utils'; import {resolvePathFromAppRoot} from '../utils';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
export class PythonCompiler extends BaseCompiler { export class PythonCompiler extends BaseCompiler {
static get key() { return 'python'; } static get key() {
return 'python';
}
constructor(compilerInfo, env) { constructor(compilerInfo, env) {
super(compilerInfo, env); super(compilerInfo, env);
@@ -69,11 +71,7 @@ export class PythonCompiler extends BaseCompiler {
} }
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
return ['-I', return ['-I', this.disasmScriptPath, '--outputfile', outputFilename, '--inputfile'];
this.disasmScriptPath,
'--outputfile',
outputFilename,
'--inputfile'];
} }
getArgumentParser() { getArgumentParser() {

View File

@@ -24,13 +24,15 @@
import path from 'path'; import path from 'path';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { resolvePathFromAppRoot } from '../utils'; import {resolvePathFromAppRoot} from '../utils';
import { BaseParser } from './argument-parsers'; import {BaseParser} from './argument-parsers';
export class RubyCompiler extends BaseCompiler { export class RubyCompiler extends BaseCompiler {
static get key() { return 'ruby'; } static get key() {
return 'ruby';
}
constructor(compilerInfo, env) { constructor(compilerInfo, env) {
super(compilerInfo, env); super(compilerInfo, env);
@@ -82,7 +84,8 @@ export class RubyCompiler extends BaseCompiler {
outputFilename, outputFilename,
'--fname', '--fname',
path.basename(this.compileFilename), path.basename(this.compileFilename),
'--inputfile']; '--inputfile',
];
} }
getArgumentParser() { getArgumentParser() {

View File

@@ -26,13 +26,15 @@ import path from 'path';
import _ from 'underscore'; import _ from 'underscore';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { parseRustOutput } from '../utils'; import {parseRustOutput} from '../utils';
import { RustParser } from './argument-parsers'; import {RustParser} from './argument-parsers';
export class RustCompiler extends BaseCompiler { export class RustCompiler extends BaseCompiler {
static get key() { return 'rust'; } static get key() {
return 'rust';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
@@ -57,7 +59,7 @@ export class RustCompiler extends BaseCompiler {
optionsForBackend(backendOptions, outputFilename) { optionsForBackend(backendOptions, outputFilename) {
// The super class handles the GCC dump files that may be needed by // The super class handles the GCC dump files that may be needed by
// rustc-cg-gcc subclass. // rustc-cg-gcc subclass.
const opts = super.optionsForBackend (backendOptions, outputFilename); const opts = super.optionsForBackend(backendOptions, outputFilename);
if (backendOptions.produceRustMir && this.compiler.supportsRustMirView) { if (backendOptions.produceRustMir && this.compiler.supportsRustMirView) {
const of = this.getRustMirOutputFilename(outputFilename); const of = this.getRustMirOutputFilename(outputFilename);
@@ -87,8 +89,7 @@ export class RustCompiler extends BaseCompiler {
// Override the IR file name method for rustc because the output file is different from clang. // Override the IR file name method for rustc because the output file is different from clang.
getIrOutputFilename(inputFilename) { getIrOutputFilename(inputFilename) {
return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase) return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase).replace('.s', '.ll');
.replace('.s', '.ll');
} }
getArgumentParser() { getArgumentParser() {

View File

@@ -24,10 +24,12 @@
import path from 'path'; import path from 'path';
import { RustCompiler } from './rust'; import {RustCompiler} from './rust';
export class RustcCgGCCCompiler extends RustCompiler { export class RustcCgGCCCompiler extends RustCompiler {
static get key() { return 'rustc-cg-gcc'; } static get key() {
return 'rustc-cg-gcc';
}
constructor(info, env) { constructor(info, env) {
super(info, env); super(info, env);
@@ -45,8 +47,8 @@ export class RustcCgGCCCompiler extends RustCompiler {
this.compiler.removeEmptyGccDump = false; this.compiler.removeEmptyGccDump = false;
} }
getGccDumpOptions(gccDumpOptions, removeEmptyPasses){ getGccDumpOptions(gccDumpOptions, removeEmptyPasses) {
return [ '-C' , 'llvm-args=' + super.getGccDumpOptions(gccDumpOptions, removeEmptyPasses).join(' ')]; return ['-C', 'llvm-args=' + super.getGccDumpOptions(gccDumpOptions, removeEmptyPasses).join(' ')];
} }
optionsForFilter(filters, outputFilename, userOptions) { optionsForFilter(filters, outputFilename, userOptions) {
@@ -54,13 +56,20 @@ export class RustcCgGCCCompiler extends RustCompiler {
// See https://github.com/antoyo/rustc_codegen_gcc // See https://github.com/antoyo/rustc_codegen_gcc
let toolroot = path.resolve(path.dirname(this.compiler.exe), '..'); let toolroot = path.resolve(path.dirname(this.compiler.exe), '..');
let options = ['-C', 'panic=abort', let options = [
'-Z', 'codegen-backend=librustc_codegen_gcc.so', '-C',
'--sysroot', toolroot + '/sysroot' ]; 'panic=abort',
'-Z',
'codegen-backend=librustc_codegen_gcc.so',
'--sysroot',
toolroot + '/sysroot',
];
// rust.js makes the asumption that LLVM is used. This may go away when cranelift is available. // rust.js makes the asumption that LLVM is used. This may go away when cranelift is available.
// Until this is the case and the super() class is refactored, simply ditch -Cllvm arg. // Until this is the case and the super() class is refactored, simply ditch -Cllvm arg.
let super_options = super.optionsForFilter(filters, outputFilename, userOptions).filter(arg => !/-Cllvm.*/.test(arg)); let super_options = super
.optionsForFilter(filters, outputFilename, userOptions)
.filter(arg => !/-Cllvm.*/.test(arg));
options = options.concat(super_options); options = options.concat(super_options);
return options; return options;
} }

View File

@@ -26,8 +26,8 @@ import Semver from 'semver';
import {asSafeVer} from '../utils'; import {asSafeVer} from '../utils';
import { ScalaParser } from './argument-parsers'; import {ScalaParser} from './argument-parsers';
import { JavaCompiler } from './java'; import {JavaCompiler} from './java';
export class ScalaCompiler extends JavaCompiler { export class ScalaCompiler extends JavaCompiler {
static get key() { static get key() {
@@ -50,8 +50,7 @@ export class ScalaCompiler extends JavaCompiler {
filterUserOptions(userOptions) { filterUserOptions(userOptions) {
// filter options without extra arguments // filter options without extra arguments
userOptions = userOptions.filter(option => userOptions = userOptions.filter(option => option !== '-Xscript');
option !== '-Xscript');
const oneArgForbiddenList = new Set([ const oneArgForbiddenList = new Set([
// -d directory // -d directory
@@ -67,13 +66,9 @@ export class ScalaCompiler extends JavaCompiler {
// Forcibly enable javap // Forcibly enable javap
filters.binary = true; filters.binary = true;
const scala2Opts = [ const scala2Opts = ['-Xlint:_'];
'-Xlint:_',
];
const scala3Opts = [ const scala3Opts = ['-deprecation'];
'-deprecation',
];
return Semver.gte(asSafeVer(this.compiler.semver), '3.0.0', true) ? scala3Opts : scala2Opts; return Semver.gte(asSafeVer(this.compiler.semver), '3.0.0', true) ? scala3Opts : scala2Opts;
} }

View File

@@ -22,10 +22,12 @@
// 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.
import { GCCCompiler } from './gcc'; import {GCCCompiler} from './gcc';
export class SdccCompiler extends GCCCompiler { export class SdccCompiler extends GCCCompiler {
static get key() { return 'sdcc'; } static get key() {
return 'sdcc';
}
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
let options = ['-o', this.filename(outputFilename)]; let options = ['-o', this.filename(outputFilename)];

View File

@@ -26,12 +26,14 @@ import path from 'path';
import _ from 'underscore'; import _ from 'underscore';
import { BaseCompiler } from '../base-compiler'; import {BaseCompiler} from '../base-compiler';
import { logger } from '../logger'; import {logger} from '../logger';
import * as utils from '../utils'; import * as utils from '../utils';
export class SPIRVCompiler extends BaseCompiler { export class SPIRVCompiler extends BaseCompiler {
static get key() { return 'spirv'; } static get key() {
return 'spirv';
}
constructor(compilerInfo, env) { constructor(compilerInfo, env) {
super(compilerInfo, env); super(compilerInfo, env);
@@ -45,8 +47,10 @@ export class SPIRVCompiler extends BaseCompiler {
backendOptions = backendOptions || {}; backendOptions = backendOptions || {};
if (this.compiler.options) { if (this.compiler.options) {
let compilerOptions = _.filter(utils.splitArguments(this.compiler.options), option => let compilerOptions = _.filter(
option !== '-fno-crash-diagnostics'); utils.splitArguments(this.compiler.options),
option => option !== '-fno-crash-diagnostics',
);
options = options.concat(compilerOptions); options = options.concat(compilerOptions);
} }
@@ -68,20 +72,21 @@ export class SPIRVCompiler extends BaseCompiler {
} }
userOptions = this.filterUserOptions(userOptions) || []; userOptions = this.filterUserOptions(userOptions) || [];
return options.concat(libIncludes, libOptions, libPaths, libLinks, userOptions, return options.concat(
[this.filename(inputFilename)], staticLibLinks); libIncludes,
libOptions,
libPaths,
libLinks,
userOptions,
[this.filename(inputFilename)],
staticLibLinks,
);
} }
optionsForFilter(filters, outputFilename) { optionsForFilter(filters, outputFilename) {
const sourceDir = path.dirname(outputFilename); const sourceDir = path.dirname(outputFilename);
const bitcodeFilename = path.join(sourceDir, this.outputFilebase + '.bc'); const bitcodeFilename = path.join(sourceDir, this.outputFilebase + '.bc');
return [ return ['-cc1', '-debug-info-kind=limited', '-dwarf-version=5', '-debugger-tuning=gdb', '-o', bitcodeFilename];
'-cc1',
'-debug-info-kind=limited',
'-dwarf-version=5',
'-debugger-tuning=gdb',
'-o', bitcodeFilename,
];
} }
getPrimaryOutputFilename(dirPath, outputFilebase) { getPrimaryOutputFilename(dirPath, outputFilebase) {
@@ -125,7 +130,7 @@ export class SPIRVCompiler extends BaseCompiler {
} }
const spvasmFilename = path.join(sourceDir, this.outputFilebase + '.spvasm'); const spvasmFilename = path.join(sourceDir, this.outputFilebase + '.spvasm');
const disassemblerFlags = [spvBinFilename, '-o', spvasmFilename]; const disassemblerFlags = [spvBinFilename, '-o', spvasmFilename];
const spvasmOutput = await this.exec(this.disassemblerPath, disassemblerFlags, execOptions); const spvasmOutput = await this.exec(this.disassemblerPath, disassemblerFlags, execOptions);
if (spvasmOutput.code !== 0) { if (spvasmOutput.code !== 0) {
@@ -152,7 +157,7 @@ export class SPIRVCompiler extends BaseCompiler {
newOptions.concat('-S'); newOptions.concat('-S');
let index = newOptions.indexOf(outputFile); let index = newOptions.indexOf(outputFile);
if (index !== -1){ if (index !== -1) {
newOptions[index] = inputFilename.replace(path.extname(inputFilename), '.ll'); newOptions[index] = inputFilename.replace(path.extname(inputFilename), '.ll');
} }
@@ -160,25 +165,28 @@ export class SPIRVCompiler extends BaseCompiler {
} }
async generateAST(inputFilename, options) { async generateAST(inputFilename, options) {
const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics') const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics').concat(['-ast-dump']);
.concat(['-ast-dump']);
const execOptions = this.getDefaultExecOptions(); const execOptions = this.getDefaultExecOptions();
execOptions.maxOutput = 1024 * 1024 * 1024; execOptions.maxOutput = 1024 * 1024 * 1024;
return this.llvmAst.processAst( return this.llvmAst.processAst(
await this.runCompilerForASTOrIR(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions)); await this.runCompilerForASTOrIR(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions),
);
} }
async generateIR(inputFilename, options, filters) { async generateIR(inputFilename, options, filters) {
const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics') const newOptions = _.filter(options, option => option !== '-fcolor-diagnostics').concat('-emit-llvm');
.concat('-emit-llvm');
const execOptions = this.getDefaultExecOptions(); const execOptions = this.getDefaultExecOptions();
execOptions.maxOutput = 1024 * 1024 * 1024; execOptions.maxOutput = 1024 * 1024 * 1024;
const output = await this.runCompilerForASTOrIR( const output = await this.runCompilerForASTOrIR(
this.compiler.exe, newOptions, this.filename(inputFilename), execOptions); this.compiler.exe,
newOptions,
this.filename(inputFilename),
execOptions,
);
if (output.code !== 0) { if (output.code !== 0) {
logger.error('Failed to run compiler to get IR code'); logger.error('Failed to run compiler to get IR code');
return output.stderr; return output.stderr;

Some files were not shown because too many files have changed in this diff Show More