使用编译器
使用命令行编译器
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/fallback
。solc
不会读取位于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)
- JSONError: JSON输入不符合要求的格式,例如输入不是JSON对象,不支持语言,等等。
- IOError: IO和导入处理错误,如提供的源中的不可解析URL或哈希不匹配。
- ParserError: 源代码不符合语言规则。
- DocstringParsingError: 无法解析注释块中的NATSPEC标签。
- SyntaxError: 语法错误,如“continue”在for循环之外使用。
- DeclarationError: 无效、不可解析或冲突的标识符名称。例如未找到标识符
- TypeError: 类型系统中的错误,如无效类型转换、无效赋值等。
- UnimplementedFeatureError:编译器不支持特性,但希望在将来的版本中得到支持。
- InternalCompilerError: 内部错误在编译器中触发,这应该作为一个问题来报告。
- Exception: 编译过程中未知的故障-这应该作为一个问题报告。
- CompilerError:编译器堆栈的使用无效——这应该作为一个问题来报告。
- FatalError: 未正确处理的致命错误-这应该作为一个问题来报告。
- Warning: 一个警告,它没有停止编译,但如果可能的话,应该加以解决。