Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows version #1540

Merged
merged 24 commits into from
Sep 29, 2020
Merged

Windows version #1540

merged 24 commits into from
Sep 29, 2020

Conversation

mxmauro
Copy link
Contributor

@mxmauro mxmauro commented Sep 22, 2020

This commit makes modifications to source code to be able to generate native Windows binaries with the help of MSYS2 build environment.

Some of the original shell scripts for building the apps were sightly modified also to work under Windows environments.

The instructions, also located in /scripts/windows/instructions.md to build the executable files are:

  1. Download and install MSYS2 package from here

  2. Run MSYS2 MingW 64-bit application to open the MSYS2 terminal.

  3. Update MSYS2 package and dependency manager by running the following commands:

    pacman -Syu --disable-download-timeout
    

    NOTE: It is very likely MSYS2 will ask to close the window and repeat the command for furter updates. Check MSYS2 web page for additional support.

  4. Install GIT on MSYS2 by executing the following command:

    pacman -S --disable-download-timeout --noconfirm git
    
  5. Clone repository with git clone https://github.com/algorand/go-algorand

  6. Switch to source code directory with cd go-algorand.

  7. Run ./scripts/windows/install_deps.sh to install required dependencies.

  8. Run make.

In /home/{you-user}/go/bin you will find all the apps. There is no installer package right know but you can copy genesis.json and create a config.json under data subdirectory and run goal node start -d data as you would do under other OSes.

image

Copy link
Contributor

@tsachiherman tsachiherman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we'll put aside that build environment changes, most of the go-code changes looks very well written and I don't have any reason to block these.
Unfortunately, I don't have the setup to test the build environment, so I can't approve this change. Maybe with some additional changes to the travis automated build, I could see how this compile successfully.

crypto/memcpy_chk_windows.c Outdated Show resolved Hide resolved
libgoal/lockedFileWindows.go Outdated Show resolved Hide resolved
util/util_windows.go Outdated Show resolved Hide resolved
@mxmauro
Copy link
Contributor Author

mxmauro commented Sep 22, 2020

Hi @tsachiherman thanks for the feedback. I'll check it better and upload fixes. BTW: Do you know the reason of the golint error Travis is throwing?

@mxmauro
Copy link
Contributor Author

mxmauro commented Sep 23, 2020

Hi @tsachiherman finally I could get rid of the issues.

Something weird I found, util_windows.go has a wrong license header but check_license.sh script started to modify all .go files because of this.

I don't how to setup Travis CI. But I asked for assistance to @rfustino to also check on Windows. Should be straight-forward. Just Windows 10 + MSYS2 and running a script to install dependencies.

Of course I can assist in whatever you need.

Copy link
Contributor

@algonautshant algonautshant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very nice.
I have some comments/questions.

Makefile Outdated
UNAME := $(shell uname)
ifneq (, $(findstring MINGW,$(UNAME)))
#Gopath is not saved across sessions, probably existing Windows env vars, override them
export GOPATH := ${HOME}/go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows (depending on the go compiler used), Go expects GOPATH to be an absolute path with the format <drive>:<path>
What will ${HOME} evaluate to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @algonautshant , The whole build process, including the installation of Go, runs inside MSYS2 ecosystem. HOME defaults to /home/{your-windows-username}.

Although you can access the whole disk with /c/..., /home and the rest of the common Unix/Linux directories are located inside MSYS2 installation path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

export GOPATH := $(shell go env GOPATH)
GOPATH1 := $(firstword $(subst :, ,$(GOPATH)))
UNAME := $(shell uname)
ifneq (, $(findstring MINGW,$(UNAME)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of evaluating ifneq (, $(findstring MINGW,$(UNAME))) every time, would be clearer to make a boolean constant for it, and check it here and elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, may be. Bash and Linux is not my strong suite. :)

@@ -38,6 +45,10 @@ endif
endif
endif

ifneq (, $(findstring MINGW,$(UNAME)))
EXTLDFLAGS := -static-libstdc++ -static-libgcc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you prefer to add to this line or remove the ones at the beginning like the rest of the file?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the indentation. I prefer adding indentation here as well. Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SInce this is ifneq, this will overwrite the EXTLDFLAGS set for linux in the previous if block won't it?

Copy link
Contributor

@tsachiherman tsachiherman Sep 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a tricky expression -
on linux, the following expression $(findstring MINGW,$(UNAME)) would evaluate to an empty string, right ?
if so, the expression ifeq (, <empty string>) is clearly true, and the ifneq (, <empty string>) is false.

On the other hand, on windows, it's the opposite. A comment above could clarify things up.

Copy link
Contributor Author

@mxmauro mxmauro Sep 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a similar approach to the one used to test flags: https://www.gnu.org/software/make/manual/make.html#Testing-Flags

network/wsNetwork_windows.go Show resolved Hide resolved
exit 1
fi

export GOPATH=$HOME/go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why configure_dev needs to export GOPATH here (only for windows)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely forgot about an old attempt to move all the actions of the /scripts/windows directory inside configure_dev.sh to normalize set up of development environment. I'll fix it.

About exporting GOPATH, because the whole process runs under some sort of virtual environment, I assume Go is not installed and I need it to run configure_dev-deps.sh, install shellcheck (there is no package available under MSYS2, and copy libwinpthread-1.dll (cannot compile statically because of karalabe/hid dependency using libusb)

@@ -41,6 +41,45 @@ function install_or_upgrade {
fi
}

function install_windoows_shellcheck() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is not needed here, since a file is added for the same purpose: scripts/windows/install_shellcheck.sh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@CLAassistant
Copy link

CLAassistant commented Sep 28, 2020

CLA assistant check
All committers have signed the CLA.

algonautshant
algonautshant previously approved these changes Sep 28, 2020
@mxmauro
Copy link
Contributor Author

mxmauro commented Sep 28, 2020

Hi @algonautshant , I moved the installation of dependencies to the configure_dev.sh script and also merged almost the latest changes from master.

Despite of this, I'm a bit lost on the failed Travis build about external arm64.

@algonautshant
Copy link
Contributor

@mxmauro your job is good. It was one of the tests timed-out. A rerun passed.

@mxmauro
Copy link
Contributor Author

mxmauro commented Sep 29, 2020

Thanks @algonautshant. Next step would be to create Travis support and an installation package using Wix (although need to see how to integrate Wix Toolset and MSYS2)

fi

# This is required because http://github.com/karalabe/hid library compiles with non-static libraries
cp /mingw64/bin/libwinpthread-1.dll $GOPATH/bin/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be cleaner to add the /mingw64/bin directory to the path on compiling machines.
For packaged deployment, we need to copy the above file anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually is already there when you open the MSYS2 MingW64 terminal:

This is my current configuration:

Blaster64@BlasterNotebook MINGW64 ~
$ echo $PATH
/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/c/Windows/System32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0/:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's already there, why do you need to copy it ? windows DLL loader would already search on the PATH, and would find it. Is there any usage of this DLL as a library source file ? i.e. building the stub out of an existing DLL ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you usually don't run the app inside MSYS2. The goal is to create executable files that can be distributed and used anywhere.

Despite it is a simple wrapper to convert pthread api into native Windows ones, I'll continue trying to remove that dependency and see if I can compile the whole code statically.

About source code, here: https://github.com/mirror/mingw-w64/tree/master/mingw-w64-libraries/winpthreads

)

// KillProcess kills a running OS process
func KillProcess(pid int, _ os.Signal) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is a great fit for the os.Signal SIGKILL. It doesn't emulate the SIGTERM correctly on windows.
Implementing it correctly require some extra work ( which can be deferred to a follow-up PR ):

  1. Add a hidden console window to the algod and configure a SetConsoleCtrlHandler
  2. In KillProcess, provide handling for SIGINT:
    Find the window that is associated with the process, and use GenerateConsoleCtrlEvent
  3. In KillProcess, provide handling for SIGTERM:
    Find the window that is associated with the process, and send WM_QUIT using SendMessage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go already sets up a SetConsoleCtrlHandler but the problem is how to send the signal to the target process.

Workarounds includes injecting a remote thread or attaching the target console (I don't like this approach)

Whatever the method, it will have some complexity.

Copy link
Contributor

@tsachiherman tsachiherman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great, thank you for your contribution.

@tsachiherman tsachiherman merged commit 0bb4cf3 into algorand:master Sep 29, 2020
@mxmauro
Copy link
Contributor Author

mxmauro commented Sep 29, 2020

You are welcome.

Next steps:

  1. Investigate about Travis CI
  2. If suits for you, use github.com/kardianos/service or build some sort of helper app to be able to launch algod as a service.
  3. Installer package.

@mxmauro mxmauro deleted the windows-version branch September 30, 2020 01:03
tsachiherman pushed a commit to tsachiherman/go-algorand that referenced this pull request Jul 7, 2021
Add support for algod to compile natively under Windows.
PhearZero pushed a commit to PhearNet/crypto that referenced this pull request Jan 17, 2025
Add support for algod to compile natively under Windows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants