Skip to content
This repository was archived by the owner on Jan 20, 2025. It is now read-only.

Windows support #16

Merged
merged 1 commit into from
Dec 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.org/asottile/setuptools-golang.svg?branch=master)](https://travis-ci.org/asottile/setuptools-golang)
[![Build status](https://ci.appveyor.com/api/projects/status/j4i2pc4o7pby3wdn/branch/master?svg=true)](https://ci.appveyor.com/project/asottile/setuptools-golang/branch/master)
[![Coverage Status](https://img.shields.io/coveralls/asottile/setuptools-golang.svg?branch=master)](https://coveralls.io/r/asottile/setuptools-golang)

setuptools-golang
Expand All @@ -13,6 +14,12 @@ This requires golang >= 1.5. It is currently tested against 1.6 and 1.7.
This requires python >= 2.7. It is currently tested against 2.7, 3.5, 3.6,
and pypy.

## Platform Support

- linux
- macos
- win32 (32 bit cpython, 32 bit go 1.10+)

## Usage

Add `setuptools-golang` to the `setup_requires` in your setup.py and
Expand Down
19 changes: 19 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
environment:
matrix:
- PYTHON: 'C:\Python27'
- PYTHON: 'C:\Python36'

install:
- 'SET PATH=%PYTHON%;%PYTHON%\Scripts;C:\MinGW\bin;C:\go-src\bin;%PATH%'
- 'SET GOROOT=C:\go-src'
- 'SET GOROOT_BOOTSTRAP=C:\go19-x86'
- 'git clone --branch=go1.10beta1 --depth=1 https://github.com/golang/go C:\go-src'
- 'cd C:\go-src\src && make.bat'
- 'pip install pytest'

# Not a C# project
build: false

test_script: pytest tests

cache: '%LOCALAPPDATA%\pip\cache'
31 changes: 25 additions & 6 deletions setuptools_golang.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
from __future__ import unicode_literals

import contextlib
import copy
import io
import os
import pipes
import shutil
import stat
import subprocess
import sys
import tempfile
Expand All @@ -19,11 +21,16 @@ def _tmpdir():
try:
yield tempdir
finally:
shutil.rmtree(tempdir)
def err(action, name, exc): # pragma: no cover (windows)
"""windows: can't remove readonly files, make them writeable!"""
os.chmod(name, stat.S_IWRITE)
action(name)

shutil.rmtree(tempdir, onerror=err)


def _get_cflags(compiler):
return ' '.join('-I{}'.format(p) for p in compiler.include_dirs)
return str(' ').join(str('-I{}').format(p) for p in compiler.include_dirs)


LFLAG_CLANG = '-Wl,-undefined,dynamic_lookup'
Expand All @@ -35,6 +42,12 @@ def _get_ldflags():
"""Determine the correct link flags. This attempts dummy compiles similar
to how autotools does feature detection.
"""
# windows gcc does not support linking with unresolved symbols
if sys.platform == 'win32': # pragma: no cover (windows)
prefix = getattr(sys, 'real_prefix', sys.prefix)
libs = os.path.join(prefix, str('libs'))
return str('-L{} -lpython{}{}').format(libs, *sys.version_info[:2])

cc = subprocess.check_output(('go', 'env', 'CC')).decode('UTF-8').strip()

with _tmpdir() as tmpdir:
Expand Down Expand Up @@ -75,7 +88,13 @@ def _raise_error(msg):

# If there are no .go files then the parent should handle this
if not any(source.endswith('.go') for source in ext.sources):
return base.build_extension(self, ext)
# the base class may mutate `self.compiler`
compiler = copy.deepcopy(self.compiler)
self.compiler, compiler = compiler, self.compiler
try:
return base.build_extension(self, ext)
finally:
self.compiler, compiler = compiler, self.compiler

if len(ext.sources) != 1:
_raise_error(
Expand All @@ -96,13 +115,13 @@ def _raise_error(msg):
shutil.copytree('.', root_path)
pkg_path = os.path.join(root_path, main_dir)

env = {'GOPATH': tempdir}
env = {str('GOPATH'): tempdir}
cmd_get = ('go', 'get', '-d')
_check_call(cmd_get, cwd=pkg_path, env=env)

env.update({
'CGO_CFLAGS': _get_cflags(self.compiler),
'CGO_LDFLAGS': _get_ldflags(),
str('CGO_CFLAGS'): _get_cflags(self.compiler),
str('CGO_LDFLAGS'): _get_ldflags(),
})
cmd_build = (
'go', 'build', '-buildmode=c-shared',
Expand Down
26 changes: 14 additions & 12 deletions tests/setuptools_golang_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def run(*cmd, **kwargs):
returncode = kwargs.pop('returncode', 0)
proc = subprocess.Popen(cmd, **kwargs)
out, err = proc.communicate()
out = out.decode('UTF-8') if out is not None else None
err = err.decode('UTF-8') if err is not None else None
out = out.decode('UTF-8').replace('\r', '') if out is not None else None
err = err.decode('UTF-8').replace('\r', '') if err is not None else None
if returncode is not None:
if proc.returncode != returncode:
raise AssertionError(
Expand Down Expand Up @@ -56,9 +56,10 @@ def venv(tmpdir_factory):
"""A shared virtualenv fixture, be careful not to install two of the same
package into this -- or sadness...
"""
bin = 'Scripts' if sys.platform == 'win32' else 'bin'
venv = tmpdir_factory.mktemp('venv').join('venv')
pip = venv.join('bin/pip').strpath
python = venv.join('bin/python').strpath
pip = venv.join(bin, 'pip').strpath
python = venv.join(bin, 'python').strpath
# Make sure this virtualenv has the same executable
run('virtualenv', venv.strpath, '-p', sys.executable)
# Install this so we can get coverage
Expand All @@ -74,9 +75,9 @@ def venv(tmpdir_factory):
@pytest.mark.parametrize(
('pkg', 'mod'),
(
('testing/sum', 'sum'),
('testing/sum_pure_go', 'sum_pure_go'),
('testing/sum_sub_package', 'sum_sub_package.sum'),
(os.path.join('testing', 'sum'), 'sum'),
(os.path.join('testing', 'sum_pure_go'), 'sum_pure_go'),
(os.path.join('testing', 'sum_sub_package'), 'sum_sub_package.sum'),
),
)
def test_sum_integration(venv, pkg, mod):
Expand All @@ -90,7 +91,8 @@ def test_sum_integration(venv, pkg, mod):

def test_integration_project_with_c(venv):
test_sum_integration(
venv, 'testing/project_with_c', 'project_with_c_sum.sum',
venv,
os.path.join('testing', 'project_with_c'), 'project_with_c_sum.sum',
)
out = run_output(venv.python, '-c', HELLO_WORLD)
assert out == 'hello world\n'
Expand All @@ -100,14 +102,14 @@ def test_integration_project_with_c(venv):


def test_integration_imports_gh(venv):
run(venv.pip, 'install', 'testing/imports_gh')
run(venv.pip, 'install', os.path.join('testing', 'imports_gh'))
out = run_output(venv.python, '-c', RED)
assert out == '\x1b[31mohai\x1b[0m\n'


def test_integration_notfound(venv):
ret = run(
venv.pip, 'install', 'testing/notfound',
venv.pip, 'install', os.path.join('testing', 'notfound'),
returncode=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
)
assert ret.returncode != 0
Expand All @@ -119,7 +121,7 @@ def test_integration_notfound(venv):

def test_integration_multidir(venv):
ret = run(
venv.pip, 'install', 'testing/multidir',
venv.pip, 'install', os.path.join('testing', 'multidir'),
returncode=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
)
assert ret.returncode != 0
Expand All @@ -133,6 +135,6 @@ def test_integration_multidir(venv):


def test_integration_internal_imports(venv):
run(venv.pip, 'install', 'testing/internal_imports')
run(venv.pip, 'install', os.path.join('testing', 'internal_imports'))
out = run_output(venv.python, '-c', OHAI)
assert out == 'ohai, Anthony\n'