diff --git a/appveyor.yml b/appveyor.yml index ef27319518..03ffdca9da 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,39 +1,40 @@ os: Visual Studio 2015 # Clone directly into GOPATH. -clone_folder: c:\gopath\src\github.com\ethereum\go-ethereum +clone_folder: C:\gopath\src\github.com\ethereum\go-ethereum clone_depth: 5 version: "{branch}.{build}" environment: global: - GOPATH: c:\gopath + GOPATH: C:\gopath CC: gcc.exe matrix: - GETH_ARCH: amd64 MSYS2_ARCH: x86_64 MSYS2_BITS: 64 MSYSTEM: MINGW64 - PATH: C:\msys64\mingw64\bin\;%PATH% + PATH: C:\msys64\mingw64\bin\;C:\Program Files (x86)\NSIS\;%PATH% - GETH_ARCH: 386 MSYS2_ARCH: i686 MSYS2_BITS: 32 MSYSTEM: MINGW32 - PATH: C:\msys64\mingw32\bin\;%PATH% + PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% install: - - rmdir c:\go /s /q + - rmdir C:\go /s /q - appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.3.windows-amd64.zip - 7z x go1.7.3.windows-amd64.zip -y -oC:\ > NUL - go version - gcc --version build_script: - - go run build\\ci.go install -arch %GETH_ARCH% + - go run build\ci.go install -arch %GETH_ARCH% after_build: - - go run build\\ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds + - go run build\ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds + - go run build\ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds test_script: - set GOARCH=%GETH_ARCH% - set CGO_ENABLED=1 - - go run build\\ci.go test -vet -coverage + - go run build\ci.go test -vet -coverage diff --git a/build/ci.go b/build/ci.go index 5dd131b1d9..e24f515879 100644 --- a/build/ci.go +++ b/build/ci.go @@ -432,7 +432,7 @@ func makeWorkdir(wdflag string) string { if wdflag != "" { err = os.MkdirAll(wdflag, 0744) } else { - wdflag, err = ioutil.TempDir("", "eth-deb-build-") + wdflag, err = ioutil.TempDir("", "geth-build-") } if err != nil { log.Fatal(err) @@ -562,27 +562,65 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { return pkgdir } -// Create Windows installer. +// Windows installer + func doWindowsInstaller(cmdline []string) { - // Create binaries that user are embedded in installer. - // The installer depends on the following packages. - cmdline = append(cmdline, "./cmd/geth", "./cmd/bootnode", "./cmd/abigen", "./cmd/disasm", "./cmd/evm", "./cmd/rlpdump") - doInstall(cmdline) + // Parse the flags and make skip installer generation on PRs + var ( + arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging") + signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`) + upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) + workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) + ) + flag.CommandLine.Parse(cmdline) + *workdir = makeWorkdir(*workdir) + env := build.Env() + maybeSkipArchive(env) - // create NSIS package - outputFile := "/DOUTPUTFILE=geth-" + makeArchiveBasename() + // Configure and run the NSIS installer maker. This assumes that all the needed + // files have been previously built (don't mix building and packaging to keep + // cross compilation complexity to a minimum). + var ( + base = archiveBasename(*arch, env) + version = strings.Split(build.VERSION(), ".") - version := strings.Split(build.VERSION(), ".") - if len(version) != 3 { - panic("Expected major.minor.build version string, got " + build.VERSION()) + majorVersion = "/DMAJORVERSION=" + version[0] + minorVersion = "/DMINORVERSION=" + version[1] + buildId = "/DBUILDVERSION=" + version[2] + buildArch = "/DARCH=" + *arch + ) + bundles := []struct { + name string + content []string + }{ + {"geth-" + base, gethArchiveFiles}, + {"geth-alltools-" + base, allToolsArchiveFiles}, } - majorVersion := "/DMAJORVERSION=" + version[0] - minorVersion := "/DMINORVERSION=" + version[1] - buildId := "/DBUILDVERSION=" + version[2] + for _, bundle := range bundles { + // Run NSIS for this specific bundle + outputFile := "/DOUTPUTFILE=" + bundle.name - cmd := exec.Command("makensis.exe", outputFile, majorVersion, minorVersion, buildId, `.\build\nsis\geth.nsi`) + tools := []string{} + for _, file := range bundle.content { + name := filepath.Base(file) + if name != "geth.exe" && name != "COPYING" { + tools = append(tools, name) + } + build.CopyFile(filepath.Join(*workdir, name), file, 0755) + } + build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil) + build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, tools) + build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, tools) + build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil) - build.MustRun(cmd) + build.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll", 0755) + makensis := exec.Command("makensis.exe", outputFile, majorVersion, minorVersion, buildId, buildArch, filepath.Join(*workdir, "geth.nsi")) + build.MustRun(makensis) + + if err := archiveUpload(filepath.Join(*workdir, bundle.name+".exe"), *upload, *signer); err != nil { + log.Fatal(err) + } + } } // Cross compilation diff --git a/build/nsis/EnvVarUpdate.nsh b/build/nsis.envvarupdate.nsh similarity index 100% rename from build/nsis/EnvVarUpdate.nsh rename to build/nsis.envvarupdate.nsh diff --git a/build/nsis/geth.nsi b/build/nsis.geth.nsi similarity index 86% rename from build/nsis/geth.nsi rename to build/nsis.geth.nsi index 5fe01697ae..8c5cf4cc5d 100644 --- a/build/nsis/geth.nsi +++ b/build/nsis.geth.nsi @@ -27,7 +27,8 @@ CRCCheck on !define GROUPNAME "Ethereum" !define APPNAME "Geth" -!define DESCRIPTION "Official golang implementation of the Ethereum protocol" +!define DESCRIPTION "Official Go implementation of the Ethereum protocol" +!addplugindir .\ # Require admin rights on NT6+ (When UAC is turned on) RequestExecutionLevel admin @@ -49,7 +50,13 @@ function .onInit # make vars are global for all users since geth is installed global setShellVarContext all !insertmacro VerifyUserIsAdmin + + ${If} ${ARCH} == "amd64" + StrCpy $InstDir "$PROGRAMFILES64\${APPNAME}" + ${Else} + StrCpy $InstDir "$PROGRAMFILES32\${APPNAME}" + ${Endif} functionEnd !include install.nsh -!include uninstall.nsh \ No newline at end of file +!include uninstall.nsh diff --git a/build/nsis/install.nsh b/build/nsis.install.nsh similarity index 94% rename from build/nsis/install.nsh rename to build/nsis.install.nsh index abbffbddb8..2a55024381 100644 --- a/build/nsis/install.nsh +++ b/build/nsis.install.nsh @@ -1,6 +1,6 @@ Name "geth ${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" # VERSION variables set through command line arguments -InstallDir "$PROGRAMFILES64\${APPNAME}" -OutFile "../bin/${OUTPUTFILE}.exe" # OUTPUTFILE set through command line arguments +InstallDir "$InstDir" +OutFile "${OUTPUTFILE}.exe" # OUTPUTFILE set through command line arguments # Links for "Add/Remove Programs" !define HELPURL "https://github.com/ethereum/go-ethereum/issues" @@ -9,17 +9,17 @@ OutFile "../bin/${OUTPUTFILE}.exe" # OUTPUTFILE set through command line argumen !define /date NOW "%Y%m%d" PageEx license - LicenseData ../../COPYING + LicenseData COPYING PageExEnd # Install geth binary Section "Geth" GETH_IDX SetOutPath $INSTDIR - file ..\bin\geth.exe + file geth.exe # Create start menu launcher createDirectory "$SMPROGRAMS\${APPNAME}" - createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" "--fast" "" + createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" "--fast" "--cache=512" createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach" "" "" createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "" "" @@ -44,11 +44,8 @@ SectionEnd # Install optional develop tools. Section /o "Development tools" DEV_TOOLS_IDX SetOutPath $INSTDIR - file ..\bin\abigen.exe - file ..\bin\bootnode.exe - file ..\bin\disasm.exe - file ..\bin\evm.exe - file ..\bin\rlpdump.exe + {{range $}}file {{$}} + {{end}} SectionEnd # Return on top of stack the total size (as DWORD) of the selected/installed sections. @@ -102,4 +99,4 @@ functionEnd Page components Page directory -Page instfiles \ No newline at end of file +Page instfiles diff --git a/build/nsis.simplefc.dll b/build/nsis.simplefc.dll new file mode 100644 index 0000000000..73b7d9634d Binary files /dev/null and b/build/nsis.simplefc.dll differ diff --git a/build/nsis/uninstall.nsh b/build/nsis.uninstall.nsh similarity index 86% rename from build/nsis/uninstall.nsh rename to build/nsis.uninstall.nsh index f275270de2..2a12fd54a2 100644 --- a/build/nsis/uninstall.nsh +++ b/build/nsis.uninstall.nsh @@ -3,12 +3,9 @@ Section "Uninstall" setShellVarContext all # Delete (optionally) installed files + {{range $}}Delete $INSTDIR\{{$}} + {{end}} Delete $INSTDIR\geth.exe - Delete $INSTDIR\abigen.exe - Delete $INSTDIR\bootnode.exe - Delete $INSTDIR\disasm.exe - Delete $INSTDIR\evm.exe - Delete $INSTDIR\rlpdump.exe Delete $INSTDIR\uninstall.exe # Delete install directory @@ -33,4 +30,4 @@ Section "Uninstall" # Cleanup registry (deletes all sub keys) DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" -SectionEnd \ No newline at end of file +SectionEnd diff --git a/internal/build/util.go b/internal/build/util.go index a821cd7f23..ce17ce220b 100644 --- a/internal/build/util.go +++ b/internal/build/util.go @@ -20,6 +20,7 @@ import ( "bytes" "flag" "fmt" + "io" "io/ioutil" "log" "os" @@ -117,3 +118,25 @@ func render(tpl *template.Template, outputFile string, outputPerm os.FileMode, x log.Fatal(err) } } + +// CopyFile copies a file. +func CopyFile(dst, src string, mode os.FileMode) { + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + log.Fatal(err) + } + destFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode) + if err != nil { + log.Fatal(err) + } + defer destFile.Close() + + srcFile, err := os.Open(src) + if err != nil { + log.Fatal(err) + } + defer srcFile.Close() + + if _, err := io.Copy(destFile, srcFile); err != nil { + log.Fatal(err) + } +}