使用编译器

翻译原文

date:20170728

使用命令行编译器

Solidity代码库的构建对象之一是solc,Solidity的命令行编译器。使用solc --help可以解释所有参数。编译器可以生成不同的输出,范围从简单的二进制和汇编一个抽象语法树(解析树)到预估gas的用量。如果你只想要编译单个文件,你只是想编译单个文件,使用命令solc --bin sourceFile.sol可以生成二进制。在你发布代码之前,如果想要在编译的时候使用优化器,可以使用命令solc --optimize --bin sourceFile.sol。如果你想要获取solc的一些更加高级的输出变量,你可以让它输出所有的信息到一个单独的文件中,使用命令solc -o outputDirectory --bin --ast --asm sourceFile.sol
命令行编译器会自动的从文件系统中导入文件,但是可能通过如下的方式,使用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/lcoal/lib/fallback目录里查找(空白的前缀总是会匹配)。solc不会在除了制定路径外的其他路径中查找文件,所以像import "/etc/passwd";只会在你添加了=/映射之后才会有效。

如果由于映射,会有多个匹配,那么会选择最多匹配的前缀。

由于安全问题,编译器会限制可访问的路径。源码的路径(和子路径)在命令行中指定,并且重定向定义的路径允许声明导入。但是其他会被拒绝。另外的路径(和子路径)可以通过--allow-paths /sample/path,/another/sample/path来切换。

如果你的合约使用到了库,你会发现字节码中包含__LibraryName______形式的字符串。你可以使用solc作为连接器,会在这些地方插入库的地址。

或者在命令行中添加--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"参数来为每个库提供地址或者把他们保存在一个文件(一个库一行)里,然后运行solc,使用--libraries fileName参数。

如果solc命令中有--link参数,所有的输入文件都会当做是没有连接的库(十六进制编码),在以上述的__LibraryName____处连接(如果输入从stdin读取,它会写到stdout中)。这种情况下,所有参数,除了--libraries都会被忽略(包含-o)。

如果solc命令中有--standard-json,它会在标准输入中接收JSON输入(会在下文叙述),并且在标准输出中返回JSON输出。

编译输入和输出的JSON描述

这些JSON格式会被用作编译器的api,也可以通过solc使用。这些可能会有更改,有些字段是可选的(已经说过了)。但是只会做一些后向兼容的更改。

编译器API期望JSON格式的输入并输出JSON格式的编译结果。

当然,注释是不允许的,这里只是为了说明情况。

输入描述
{
  // 必须字段:源码语言,可以是"Solidity", "serpent", "lll", "assembly", 等等
  language: "Solidity",
  // 必须字段
  sources:
  {
    // 键是源文件的“全局”名称。
    // imports可以使用其他重定向的文件(看下文)
    "myFile.sol":
    {
      // 可选的参数: 源文件的keccak256 hash值
      // 如果它被导入,它会被用来验证获得的内容。 
      "keccak256": "0x123...",
      // 必须字段(除非使用了“content”字段,看下文): 源文件的URL(s)
      // URL(s) 应该按顺序导入,并且结果要进行keccak256验证。如果hash值不匹配,或者不能正确加载URL(s),就会产生一个错误。
      "urls":
      [
        "bzzr://56ab...",
        "ipfs://Qma...",
        "file:///tmp/path/to/file.sol"
      ]
    },
    "mortal":
    {
      // 可选字段:源文件的keccak256 hash值
      Optional: keccak256 hash of the source file
      "keccak256": "0x234...",
      // 必须字段(除非“urls”字段被使用): 源文件的字面量信息
      "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
    }
  },
  // 可选字段
  settings:
  {
    // 可选字段: 排过序的重定向
    remappings: [ ":g/dir" ],
    // 可选字段: 优化器设置(enabled默认为false)
    optimizer: {
      enabled: true,
      runs: 500
    },
    // 元数据设置 (可选的)
    metadata: {
      // 只能使用字面量内容,并且不能有URLs(默认不支持)。
      useLiteralContent: true
    },
    // 库的地址。如果这里没有给出所有的库,这会导致生成没有连接的对象,这些对象的输出是不同的。
    libraries: {
      // 最上层的键是所需库的源文件的名称。
      // 如果使用了重定向,这些源文件会在映射作用之后匹配全局路径。
      // 如果键是空字符串,他会被引用到全局层级。
      "myFile.sol": {
        "MyLib": "0x123123..."
      }
    }
    // 下面的参数可以用来指定期望的输出。
    // 如果没有这个字段,编译器会载入并做类型检测,但是不会生成其他输出。除非出现错误。
    // 第一层的键是文件的名称,第二层是合约的名称,如果合约的名称为空,会引用文件的名称。
    // 星号代表着所有合约
    //
    // 有效的输出类型如下所示:
    //   abi - ABI
    //   ast - 所有源文件的AST
    //   legacyAST - 所有源文件的legacy AST 
    //   devdoc - 开发文档 (natspec)
    //   userdoc - 用户手册 (natspec)
    //   metadata - 元素据
    //   ir - 在去语法糖之前的新汇编形式 
    //   evm.assembly - 在去语法糖之后的新汇编形式 
    //   evm.legacyAssembly - JSON格式的旧类型的汇编形式
    //   evm.bytecode.object - 字节码对象
    //   evm.bytecode.opcodes - 操作码列表
    //   evm.bytecode.sourceMap - 源码映射(调试很有用)
    //   evm.bytecode.linkReferences - 引用连接 (如果是没有连接的对象)
    //   evm.deployedBytecode* - 发布字节码 (和evm.bytecode有相同的选项)
    //   evm.methodIdentifiers - 函数列表的hash
    //   evm.gasEstimates - gas估计函数
    //   ewasm.wast - eWASM S-表达式 格式 (不支持 atm)
    //   ewasm.wasm - eWASM 二进制格式 (不支持 atm)
    //
    // 注意使用 `evm`, `evm.bytecode`, `ewasm`, 等. 会选择输出的每个目标部分
    //
    outputSelection: {
      // 使能每个简单合约的元数据和字节码
      "*": {
        "*": [ "metadata", "evm.bytecode" ]
      },
      // 对文件def,使能 MyContract合约的abi和操作码输出。
      "def": {
        "MyContract": [ "abi", "evm.opcodes" ]
      },
      // 使能每个合约的源映射
      "*": {
        "*": [ "evm.sourceMap" ]
      },
      // 使能每个文件的legacyAST输出
      "*": {
        "": [ "legacyAST" ]
      }
    }
  }
}
输出描述
{
  // 可选字段:如果没有错误或者警告,就不会生成这个字段。
  errors: [
    {
      // 可选字段:源文件的位置
      sourceLocation: {
        file: "sourceFile.sol",
        start: 0,
        end: 100
      ],
      // 强制的: 错误类型,如"TypeError", "InternalCompilerError", "Exception", 等
      type: "TypeError",
      // 强制的: 发生错误的组件,如"general", "ewasm", 等
      component: "general",
      // 强制的 ("error" 或者 "warning")
      severity: "error",
      // 强制的
      message: "Invalid keyword"
      // 可选的: 格式化的信息,说明出错的源码位置。
      formattedMessage: "sourceFile.sol:100: Invalid keyword"
    }
  ],
  // 这包含文件层级的输出,它通过 outputSelection 设置来限制或者过滤。
  sources: {
    "sourceFile.sol": {
      // 标识符 (用于源码映射)
      id: 1,
      // AST 对象
      ast: {},
      // legacy AST 对象
      legacyAST: {}
    }
  },
  // 这里包含合约层级的输出。可以通过 outputSelection 设置来限制或者过滤.
  contracts: {
    "sourceFile.sol": {
      // 如果语言没有合约名称,这个字段像是空字段。
      "ContractName": {
        // 以太坊合约 ABI. 如果为空,会呈现为空数组。
        // 详情查看 https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
        abi: [],
        // 查看输出文档的元数据 (JSON 字符串连载)
        metadata: "{...}",
        // 用户手册 (natspec)
        userdoc: {},
        // 开发文档 (natspec)
        devdoc: {},
        // 中间件(字符串)
        ir: "",
        // EVM-相关输出
        evm: {
          // 汇编 (字符串)
          assembly: "",
          // 旧格式汇编 (对象)
          legacyAssembly: {},
          // 字节码和相关详情
          bytecode: {
            // 十六进制字符串的字节码
            object: "00fe",
            // 操作码列表 (字符串)
            opcodes: "",
            // 字符串形式的源码映射。查看源码映射定义。
            sourceMap: "",
            // 如果给定这个字段,这是未连接的对象
            linkReferences: {
              "libraryFile.sol": {
                // 字节码偏移。连接会在指定位置替换20字节
                Byte offsets into the bytecode. Linking replaces the 20 bytes located there.
                "Library1": [
                  { start: 0, length: 20 },
                  { start: 200, length: 20 }
                ]
              }
            }
          },
          // 和上面字段结构相同
          deployedBytecode: { },
          // 函数列表的哈希
          methodIdentifiers: {
            "delegate(address)": "5c19a95c"
          },
          // 函数 gas 估计
          gasEstimates: {
            creation: {
              codeDepositCost: "420000",
              executionCost: "infinite",
              totalCost: "infinite"
            },
            external: {
              "delegate(address)": "25000"
            },
            internal: {
              "heavyLifting()": "infinite"
            }
          }
        },
        // eWASM 相关的输出
        ewasm: {
          // S-表达式 格式
          wast: "",
          // 二进制格式 (十六进制字符串)
          wasm: ""
        }
      }
    }
  }
}

你可能感兴趣的:(使用编译器)