Solidity語言學習筆記————2、使用編譯器

FLy_鵬程萬里發表於2018-06-22

使用編譯器

使用命令列編譯器

Solidity的其中一個編譯器是solc,即Solidity命令列編譯器。

  • 使用solc --help提供對所有選項的闡述。編譯器可以生成各種型別的輸出,包括簡單的二進位制檔案、抽象語法樹(解析樹)的彙編以及預計要花費的gas。
  • 如果僅僅想編譯一個智慧合約,可以用solc --bin sourceFile.sol命令print二進位制資料。
  • 在部署合約之前,使用solc --optimize --bin sourceFile.sol命令可以優化編譯。
  • 使用solc -o outputDirectory --bin --ast --asm sourceFile.sol命令可以使 solc 編譯出更高階型別的輸出檔案,並儲存到 outputDirectory。

命令列編譯器將自動從檔案系統讀取匯入的檔案,但也可以通過以下方式使用prefix = path提供路徑重定向:

solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol

這基本上指示編譯器在/usr/local/lib/dapp-bin下面搜尋任何以github.com/ethereum/dapp-bin/開頭的內容,如果它沒有找到檔案,它將檢視/usr/local/lib/fallbacksolc不會讀取位於remappings目標之外的檔案系統和位於顯式指定的原始檔駐留的目錄之外的檔案,因此如import "/etc/passwd"之類的內容;僅當新增/=作為remappings時才有效。

如果由於remappings有多個匹配,則選擇具有最長公共字首的匹配。

為了安全起見,編譯器會限制目錄訪問許可權。匯入語句(import)只可以訪問命令列指定的原始檔的路徑(及其子目錄)和重新對映定義的路徑,其他所有內容都會被拒絕。 額外的路徑可以通過solc --allow-paths /sample/path,/another/sample/path命令來新增。

如果合約使用了 libraries ,位元組碼中將會包含 __LibraryName______ 形式的子字串。可以用 solc 作為聯結器插入庫地址:

  • 直接在命令列指定庫後編譯
solc --libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"
  • 在檔案中指定(一個庫一行),然後用下面命令編譯
solc --libraries fileName

如果使用選項 --link 呼叫 solc,所有輸入檔案將被編譯為上面給出的 __LibraryName ____ 格式的非連結二進位制檔案(十六進位制編碼),然後進行本地連結(如果輸入是從 stdin 讀取的,則寫入到 stdout)。在這種情況下,除了 --libraries 之外的其他選項都將被忽略(包括 -o )。

如果使用 --standard-json 選項呼叫 solc ,那麼它將會在標準輸入中輸入JSON(如下所述),並在標準輸出上返回一個JSON輸出。

編譯器輸入輸出JSON描述

這些JSON格式資料由編譯器API使用,也可以通過 solc 使用。這些是更改的主題,一些欄位也是可選的(如所述),但其目的僅在於使改變向後相容。

編譯器API期望使用JSON格式的輸入,並以JSON格式輸出輸出編譯結果。

註釋當然是不允許的,在這僅供說明之用。

輸入說明

{
  // Required: Source code language, such as "Solidity", "serpent", "lll", "assembly", etc.
  language: "Solidity",
  // Required
  sources:
  {
    // The keys here are the "global" names of the source files,
    // imports can use other files via remappings (see below).
    "myFile.sol":
    {
      // Optional: keccak256 hash of the source file
      // It is used to verify the retrieved content if imported via URLs.
      "keccak256": "0x123...",
      // Required (unless "content" is used, see below): URL(s) to the source file.
      // URL(s) should be imported in this order and the result checked against the
      // keccak256 hash (if available). If the hash doesn't match or none of the
      // URL(s) result in success, an error should be raised.
      "urls":
      [
        "bzzr://56ab...",
        "ipfs://Qma...",
        "file:///tmp/path/to/file.sol"
      ]
    },
    "mortal":
    {
      // Optional: keccak256 hash of the source file
      "keccak256": "0x234...",
      // Required (unless "urls" is used): literal contents of the source file
      "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
    }
  },
  // Optional
  settings:
  {
    // Optional: Sorted list of remappings
    remappings: [ ":g/dir" ],
    // Optional: Optimizer settings (enabled defaults to false)
    optimizer: {
      enabled: true,
      runs: 500
    },
    // Metadata settings (optional)
    metadata: {
      // Use only literal content and not URLs (false by default)
      useLiteralContent: true
    },
    // Addresses of the libraries. If not all libraries are given here, it can result in unlinked objects whose output data is different.
    libraries: {
      // The top level key is the the name of the source file where the library is used.
      // If remappings are used, this source file should match the global path after remappings were applied.
      // If this key is an empty string, that refers to a global level.
      "myFile.sol": {
        "MyLib": "0x123123..."
      }
    }
    // The following can be used to select desired outputs.
    // If this field is omitted, then the compiler loads and does type checking, but will not generate any outputs apart from errors.
    // The first level key is the file name and the second is the contract name, where empty contract name refers to the file itself,
    // while the star refers to all of the contracts.
    //
    // The available output types are as follows:
    //   abi - ABI
    //   ast - AST of all source files
    //   legacyAST - legacy AST of all source files
    //   devdoc - Developer documentation (natspec)
    //   userdoc - User documentation (natspec)
    //   metadata - Metadata
    //   ir - New assembly format before desugaring
    //   evm.assembly - New assembly format after desugaring
    //   evm.legacyAssembly - Old-style assembly format in JSON
    //   evm.bytecode.object - Bytecode object
    //   evm.bytecode.opcodes - Opcodes list
    //   evm.bytecode.sourceMap - Source mapping (useful for debugging)
    //   evm.bytecode.linkReferences - Link references (if unlinked object)
    //   evm.deployedBytecode* - Deployed bytecode (has the same options as evm.bytecode)
    //   evm.methodIdentifiers - The list of function hashes
    //   evm.gasEstimates - Function gas estimates
    //   ewasm.wast - eWASM S-expressions format (not supported atm)
    //   ewasm.wasm - eWASM binary format (not supported atm)
    //
    // Note that using a using `evm`, `evm.bytecode`, `ewasm`, etc. will select every
    // target part of that output. Additionally, `*` can be used as a wildcard to request everything.
    //
    outputSelection: {
      // Enable the metadata and bytecode outputs of every single contract.
      "*": {
        "*": [ "metadata", "evm.bytecode" ]
      },
      // Enable the abi and opcodes output of MyContract defined in file def.
      "def": {
        "MyContract": [ "abi", "evm.bytecode.opcodes" ]
      },
      // Enable the source map output of every single contract.
      "*": {
        "*": [ "evm.bytecode.sourceMap" ]
      },
      // Enable the legacy AST output of every single file.
      "*": {
        "": [ "legacyAST" ]
      }
    }
  }
}

輸出說明

{
  // Optional: not present if no errors/warnings were encountered
  errors: [
    {
      // Optional: Location within the source file.
      sourceLocation: {
        file: "sourceFile.sol",
        start: 0,
        end: 100
      ],
      // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
      // See below for complete list of types.
      type: "TypeError",
      // Mandatory: Component where the error originated, such as "general", "ewasm", etc.
      component: "general",
      // Mandatory ("error" or "warning")
      severity: "error",
      // Mandatory
      message: "Invalid keyword"
      // Optional: the message formatted with source location
      formattedMessage: "sourceFile.sol:100: Invalid keyword"
    }
  ],
  // This contains the file-level outputs. In can be limited/filtered by the outputSelection settings.
  sources: {
    "sourceFile.sol": {
      // Identifier (used in source maps)
      id: 1,
      // The AST object
      ast: {},
      // The legacy AST object
      legacyAST: {}
    }
  },
  // This contains the contract-level outputs. It can be limited/filtered by the outputSelection settings.
  contracts: {
    "sourceFile.sol": {
      // If the language used has no contract names, this field should equal to an empty string.
      "ContractName": {
        // The Ethereum Contract ABI. If empty, it is represented as an empty array.
        // See https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
        abi: [],
        // See the Metadata Output documentation (serialised JSON string)
        metadata: "{...}",
        // User documentation (natspec)
        userdoc: {},
        // Developer documentation (natspec)
        devdoc: {},
        // Intermediate representation (string)
        ir: "",
        // EVM-related outputs
        evm: {
          // Assembly (string)
          assembly: "",
          // Old-style assembly (object)
          legacyAssembly: {},
          // Bytecode and related details.
          bytecode: {
            // The bytecode as a hex string.
            object: "00fe",
            // Opcodes list (string)
            opcodes: "",
            // The source mapping as a string. See the source mapping definition.
            sourceMap: "",
            // If given, this is an unlinked object.
            linkReferences: {
              "libraryFile.sol": {
                // Byte offsets into the bytecode. Linking replaces the 20 bytes located there.
                "Library1": [
                  { start: 0, length: 20 },
                  { start: 200, length: 20 }
                ]
              }
            }
          },
          // The same layout as above.
          deployedBytecode: { },
          // The list of function hashes
          methodIdentifiers: {
            "delegate(address)": "5c19a95c"
          },
          // Function gas estimates
          gasEstimates: {
            creation: {
              codeDepositCost: "420000",
              executionCost: "infinite",
              totalCost: "infinite"
            },
            external: {
              "delegate(address)": "25000"
            },
            internal: {
              "heavyLifting()": "infinite"
            }
          }
        },
        // eWASM related outputs
        ewasm: {
          // S-expressions format
          wast: "",
          // Binary format (hex string)
          wasm: ""
        }
      }
    }
  }
}

錯誤型別(Error types)

  1. JSONError: JSON輸入不符合要求的格式,例如輸入不是JSON物件,不支援語言,等等。
  2. IOError: IO和匯入處理錯誤,如提供的源中的不可解析URL或雜湊不匹配。
  3. ParserError: 原始碼不符合語言規則。
  4. DocstringParsingError: 無法解析註釋塊中的NATSPEC標籤。
  5. SyntaxError: 語法錯誤,如“continue”在for迴圈之外使用。
  6. DeclarationError: 無效、不可解析或衝突的識別符號名稱。例如未找到識別符號
  7. TypeError: 型別系統中的錯誤,如無效型別轉換、無效賦值等。
  8. UnimplementedFeatureError:編譯器不支援特性,但希望在將來的版本中得到支援。
  9. InternalCompilerError: 內部錯誤在編譯器中觸發,這應該作為一個問題來報告。
  10. Exception: 編譯過程中未知的故障-這應該作為一個問題報告。
  11. CompilerError:編譯器堆疊的使用無效——這應該作為一個問題來報告。
  12. FatalError: 未正確處理的致命錯誤-這應該作為一個問題來報告。
  13. Warning: 一個警告,它沒有停止編譯,但如果可能的話,應該加以解決。

相關文章