diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go index 3a1ae6f4c3..f63b3fa7a7 100644 --- a/cmd/abigen/main.go +++ b/cmd/abigen/main.go @@ -29,9 +29,10 @@ import ( ) var ( - abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind") - binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)") - typFlag = flag.String("type", "", "Struct name for the binding (default = package name)") + abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind") + binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)") + typFlag = flag.String("type", "", "Struct name for the binding (default = package name)") + linkFlag = flag.String("link", "", "Library flag linker for name to addresses in the code") solFlag = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind") solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested") diff --git a/common/compiler/compiler.go b/common/compiler/compiler.go new file mode 100644 index 0000000000..e95c45ae9e --- /dev/null +++ b/common/compiler/compiler.go @@ -0,0 +1,6 @@ +package compiler + +type Compiler interface { + PrepareCommand(files ...string) error + Compile(flags ...func() string) (string, error) +} diff --git a/common/compiler/flags.go b/common/compiler/flags.go new file mode 100644 index 0000000000..3c587120f4 --- /dev/null +++ b/common/compiler/flags.go @@ -0,0 +1,17 @@ +package compiler + +func addStandardAbiAndBin() string { + return "abi,bin," +} + +func addDevDoc() string { + return "devdoc" +} + +func addUserDoc() string { + return "userdoc" +} + +func addMetadata() string { + return "metadata" +} diff --git a/common/compiler/solidity.go b/common/compiler/solidity.go index abb8039896..6e69136834 100644 --- a/common/compiler/solidity.go +++ b/common/compiler/solidity.go @@ -23,6 +23,7 @@ import ( "errors" "fmt" "io/ioutil" + "os" "os/exec" "regexp" "strconv" @@ -52,6 +53,15 @@ type ContractInfo struct { type Solidity struct { Path, Version, FullVersion string Major, Minor, Patch int + Files []string + FlagOpts SolcFlagOpts +} + +type SolcFlagOpts struct { + Optimize bool + CombinedJson []string + ToLink []string + Version string } // --combined-output format @@ -136,6 +146,35 @@ func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, return s.run(cmd, source) } +func (s *Solidity) GetFiles(sourcefiles ...string) error { + if len(sourcefiles) == 0 { + return errors.New("solc: no source files") + } + + for _, file := range sourcefiles { + if _, err := os.Stat(file); os.IsNotExist(err) { + return fmt.Errorf("solc: could not find file %v", file) + } + s.Files = append(s.Files, file) + } + return nil +} + +/*func (s *Solidity) Compile(flags ...func() string) (string, error) { + var command []string + for _, flag := range flags { + command := append(command, flag()) + } + if len(s.FlagOpts.ToLink) > 0 { + command := append(command, s.linkLibraries()) + } + + finalCommand := strings.Join(command, "") + + exec.Command("solc", finalCommand) + +}*/ + func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, error) { var stderr, stdout bytes.Buffer cmd.Stderr = &stderr @@ -182,6 +221,10 @@ func (s *Solidity) run(cmd *exec.Cmd, source string) (map[string]*Contract, erro return contracts, nil } +func (s *Solidity) linkLibraries() string { + return "--libraries " + strings.Join(s.FlagOpts.ToLink, ",") +} + func slurpFiles(files []string) (string, error) { var concat bytes.Buffer for _, file := range files { diff --git a/common/compiler/solidity_test.go b/common/compiler/solidity_test.go index 0da3bb337e..d248720e0d 100644 --- a/common/compiler/solidity_test.go +++ b/common/compiler/solidity_test.go @@ -18,6 +18,7 @@ package compiler import ( "os/exec" + "strings" "testing" ) @@ -30,6 +31,40 @@ contract test { } } ` + librarySource = ` +library Set { + struct Data { mapping(uint => bool) flags; } + function insert(Data storage self, uint value) + returns (bool) + { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) + returns (bool) + { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) + returns (bool) + { + return self.flags[value]; + } +} + +contract C { + Set.Data knownValues; + function register(uint value) { + require(Set.insert(knownValues, value)); + } +}` ) func skipWithoutSolc(t *testing.T) { @@ -75,3 +110,21 @@ func TestCompileError(t *testing.T) { } t.Logf("error: %v", err) } + +func TestCompilerLinking(t *testing.T) { + skipWithoutSolc(t) + + solc, err := SolidityVersion("") + if err != nil { + t.Fatalf("%v", err) + } + + solc.FlagOpts.ToLink = append(solc.FlagOpts.ToLink, "Set:0x692a70d2e424a56d2c6c27aa97d1a86395877b3a") + + linkedLibraries := solc.linkLibraries() + + testingCase1 := "--libraries Set:0x692a70d2e424a56d2c6c27aa97d1a86395877b3a" + if strings.Compare(linkedLibraries, testingCase1) != 0 { + t.Errorf("expected %v, got %v", linkedLibraries, testingCase1) + } +}