Unverified Commit 78860a3f authored by Mccaskey, Alex's avatar Mccaskey, Alex Committed by GitHub
Browse files

Merge pull request #54 from czhao39/master

Basic plugin generator
parents 28028256 5d5c7db1
......@@ -39,3 +39,4 @@
/wheelhouse/
**/.ipynb_checkpoints
compile_commands.json
__pycache__/
......@@ -102,8 +102,7 @@ public:
TEST(PyXACCCompilerTester, checkSimple) {
auto compiler = std::make_shared<PyXACCCompiler>();
auto compiler = xacc::getService<xacc::Compiler>("xacc-py");
const std::string src = R"src(def f(theta):
X(0)
Rx(theta,0)
......@@ -128,6 +127,6 @@ int main(int argc, char** argv) {
xacc::Initialize(argc, argv);
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
// xacc::Finalize();
return ret;
}
from _pyxacc import *
import os, platform, sys, sysconfig
import argparse, inspect
from xaccplugingen import xaccplugingen
def parse_args(args):
parser = argparse.ArgumentParser(description="XACC Framework Utility.",
parser = argparse.ArgumentParser(description="XACC Framework Utility.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
fromfile_prefix_chars='@')
parser.add_argument("-c", "--set-credentials", type=str, help="Set your credentials for any of the remote Accelerators.", required=False)
parser.add_argument("-k", "--api-key", type=str, help="The API key for the remote Accelerators.", required=False)
parser.add_argument("-u", "--user-id", type=str, help="The User Id for the remote Accelerators.", required=False)
parser.add_argument("--url", type=str, help="The URL for the remote Accelerators.", required=False)
parser.add_argument("-L", "--location", action='store_true', help="Print the path to the XACC install location.", required=False)
parser.add_argument("--python-include-dir", action='store_true', help="Print the path to the Python.h.", required=False)
parser.add_argument("-b", "--branch", default='master',type=str, help="Print the path to the XACC install location.", required=False)
opts = parser.parse_args(args)
if opts.set_credentials and not opts.api_key:
print('Error in arg input, must supply api-key if setting credentials')
sys.exit(1)
return opts
parser.add_argument("-c", "--set-credentials", type=str,
help="Set your credentials for any of the remote Accelerators.", required=False)
parser.add_argument("-k", "--api-key", type=str, help="The API key for the remote Accelerators.", required=False)
parser.add_argument("-u", "--user-id", type=str, help="The User Id for the remote Accelerators.", required=False)
parser.add_argument("--url", type=str, help="The URL for the remote Accelerators.", required=False)
parser.add_argument("-L", "--location", action='store_true', help="Print the path to the XACC install location.",
required=False)
parser.add_argument("--python-include-dir", action='store_true', help="Print the path to the Python.h.",
required=False)
parser.add_argument("-b", "--branch", default='master', type=str,
help="Print the path to the XACC install location.", required=False)
subparsers = parser.add_subparsers(title="subcommands", dest="subcommand",
description="Run {} [subcommand] -h for more information about a specific subcommand".format(
os.path.basename(sys.argv[0])))
xaccplugingen.add_subparser(subparsers)
opts = parser.parse_args(args)
if opts.set_credentials and not opts.api_key:
print('Error in arg input, must supply api-key if setting credentials')
sys.exit(1)
return opts
def initialize():
xaccHome = os.environ['HOME']+'/.xacc'
if not os.path.exists(xaccHome):
os.makedirs(xaccHome)
try:
file = open(xaccHome+'/.internal_plugins', 'r')
contents = file.read()
except IOError:
file = open(xaccHome+'/.internal_plugins', 'w')
contents = ''
file.close()
file = open(xaccHome+'/.internal_plugins', 'w')
xaccLocation = os.path.dirname(os.path.realpath(__file__))
if platform.system() == "Darwin":
libname1 = "libxacc-quantum-gate.dylib"
libname2 = "libxacc-quantum-aqc.dylib"
else:
libname1 = "libxacc-quantum-gate.so"
libname2 = "libxacc-quantum-aqc.so"
if xaccLocation+'/lib/'+libname1+'\n' not in contents:
file.write(xaccLocation+'/lib/'+libname1+'\n')
if xaccLocation+'/lib/'+libname2+'\n' not in contents:
file.write(xaccLocation+'/lib/'+libname2+'\n')
file.write(contents)
file.close()
setIsPyApi()
xaccHome = os.environ['HOME'] + '/.xacc'
if not os.path.exists(xaccHome):
os.makedirs(xaccHome)
try:
file = open(xaccHome + '/.internal_plugins', 'r')
contents = file.read()
except IOError:
file = open(xaccHome + '/.internal_plugins', 'w')
contents = ''
file.close()
file = open(xaccHome + '/.internal_plugins', 'w')
xaccLocation = os.path.dirname(os.path.realpath(__file__))
if platform.system() == "Darwin":
libname1 = "libxacc-quantum-gate.dylib"
libname2 = "libxacc-quantum-aqc.dylib"
else:
libname1 = "libxacc-quantum-gate.so"
libname2 = "libxacc-quantum-aqc.so"
if xaccLocation + '/lib/' + libname1 + '\n' not in contents:
file.write(xaccLocation + '/lib/' + libname1 + '\n')
if xaccLocation + '/lib/' + libname2 + '\n' not in contents:
file.write(xaccLocation + '/lib/' + libname2 + '\n')
file.write(contents)
file.close()
setIsPyApi()
def setCredentials(opts):
defaultUrls = {'ibm':'https://quantumexperience.ng.bluemix.net','rigetti':'https://api.rigetti.com/qvm', 'dwave':'https://cloud.dwavesys.com'}
acc = opts.set_credentials
url = opts.url if not opts.url == None else defaultUrls[acc]
if acc == 'rigetti' and not os.path.exists(os.environ['HOME']+'/.pyquil_config'):
apikey = opts.api_key
if opts.user_id == None:
print('Error, must provide user-id for Rigetti accelerator')
sys.exit(1)
user = opts.user_id
f = open(os.environ['HOME']+'/.pyquil_config','w')
f.write('[Rigetti Forest]\n')
f.write('key: ' + apikey + '\n')
f.write('user_id: ' + user + '\n')
f.write('url: ' + url + '\n')
f.close()
else:
if not os.path.exists(os.environ['HOME']+'/.'+acc+'_config'):
f = open(os.environ['HOME']+'/.'+acc+'_config','w')
f.write('key: '+ opts.api_key + '\n')
f.write('url: '+ url + '\n')
f.close()
fname = acc if 'rigetti' not in acc else 'pyquil'
print('\nCreated '+acc+' config file:\n$ cat ~/.'+fname+'_config:')
print(open(os.environ['HOME']+'/.'+fname+'_config','r').read())
defaultUrls = {'ibm': 'https://quantumexperience.ng.bluemix.net', 'rigetti': 'https://api.rigetti.com/qvm',
'dwave': 'https://cloud.dwavesys.com'}
acc = opts.set_credentials
url = opts.url if not opts.url == None else defaultUrls[acc]
if acc == 'rigetti' and not os.path.exists(os.environ['HOME'] + '/.pyquil_config'):
apikey = opts.api_key
if opts.user_id == None:
print('Error, must provide user-id for Rigetti accelerator')
sys.exit(1)
user = opts.user_id
f = open(os.environ['HOME'] + '/.pyquil_config', 'w')
f.write('[Rigetti Forest]\n')
f.write('key: ' + apikey + '\n')
f.write('user_id: ' + user + '\n')
f.write('url: ' + url + '\n')
f.close()
else:
if not os.path.exists(os.environ['HOME'] + '/.' + acc + '_config'):
f = open(os.environ['HOME'] + '/.' + acc + '_config', 'w')
f.write('key: ' + opts.api_key + '\n')
f.write('url: ' + url + '\n')
f.close()
fname = acc if 'rigetti' not in acc else 'pyquil'
print('\nCreated ' + acc + ' config file:\n$ cat ~/.' + fname + '_config:')
print(open(os.environ['HOME'] + '/.' + fname + '_config', 'r').read())
class qpu(object):
def __init__(self, *args, **kwargs):
......@@ -126,18 +141,24 @@ class qpu(object):
return wrapped_f
def main(argv=None):
opts = parse_args(sys.argv[1:])
xaccLocation = os.path.dirname(os.path.realpath(__file__))
if opts.location:
print(xaccLocation)
sys.exit(0)
if opts.python_include_dir:
print(sysconfig.get_paths()['platinclude'])
sys.exit(0)
if not opts.set_credentials == None:
setCredentials(opts)
opts = parse_args(sys.argv[1:])
if opts.subcommand == "generate-plugin":
xaccplugingen.run_generator(opts)
sys.exit(0)
xaccLocation = os.path.dirname(os.path.realpath(__file__))
if opts.location:
print(xaccLocation)
sys.exit(0)
if opts.python_include_dir:
print(sysconfig.get_paths()['platinclude'])
sys.exit(0)
if not opts.set_credentials == None:
setCredentials(opts)
initialize()
......
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project({lib_name} LANGUAGES CXX)
option({project_name_upper}_BUILD_TESTS "Build test programs" OFF)
set(CMAKE_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
message(STATUS "C++ version ${{CXX_STANDARD}} configured.")
find_package(XACC REQUIRED)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set (CMAKE_INSTALL_PREFIX "${{XACC_ROOT}}" CACHE PATH "default install path" FORCE )
endif()
set(CppMicroServicesConfig_DIR "${{XACC_ROOT}}/share/cppmicroservices4/cmake")
set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} "${{XACC_ROOT}}/share/xacc")
set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} "${{CppMicroServicesConfig_DIR}}")
include(tests)
include(CppMicroServicesConfig)
include_directories(${{XACC_INCLUDE_DIRS}})
link_directories(${{XACC_LIBRARY_DIR}})
add_subdirectory(compiler)
if(PYTHON_INCLUDE_DIR)
add_subdirectory(python)
endif()
if({project_name_upper}_BUILD_TESTS)
include_directories(${{CMAKE_SOURCE_DIR}}/compiler)
add_subdirectory(tests)
endif()
set (PACKAGE_NAME "Generated XACC Compiler")
set (PACKAGE_DESCRIPTION "Generated XACC Compiler Bundle")
set (LIBRARY_NAME {compiler_lib_name})
file (GLOB_RECURSE HEADERS *.hpp)
file (GLOB SRC *.cpp)
# Set up dependencies to resources to track changes
usFunctionGetResourceSource(TARGET ${{LIBRARY_NAME}} OUT SRC)
# Generate bundle initialization code
usFunctionGenerateBundleInit(TARGET ${{LIBRARY_NAME}} OUT SRC)
add_library(${{LIBRARY_NAME}} SHARED ${{SRC}})
set(_bundle_name {compiler_bundle_name})
set_target_properties(${{LIBRARY_NAME}} PROPERTIES
# This is required for every bundle
COMPILE_DEFINITIONS US_BUNDLE_NAME=${{_bundle_name}}
# This is for convenience, used by other CMake functions
US_BUNDLE_NAME ${{_bundle_name}}
)
# Embed meta-data from a manifest.json file
usFunctionEmbedResources(TARGET ${{LIBRARY_NAME}}
WORKING_DIRECTORY
${{CMAKE_CURRENT_SOURCE_DIR}}
FILES
manifest.json
)
target_link_libraries(${{LIBRARY_NAME}} ${{XACC_LIBRARIES}})
if(APPLE)
set_target_properties(${{LIBRARY_NAME}} PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${{LIBRARY_NAME}} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${{LIBRARY_NAME}} PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${{LIBRARY_NAME}} PROPERTIES LINK_FLAGS "-shared")
endif()
install(TARGETS ${{LIBRARY_NAME}} DESTINATION ${{CMAKE_INSTALL_PREFIX}}/plugins)
{{
"bundle.symbolic_name" : "{compiler_lib_name}",
"bundle.activator" : true,
"bundle.name" : "Generated XACC Compiler",
"bundle.description" : "This is an automatically generated bundle."
}}
#include "{compiler_class_name}.hpp"
#include "XACC.hpp"
#include "IRProvider.hpp"
namespace xacc {{
namespace quantum {{
{compiler_class_name}::{compiler_class_name}() = default;
std::shared_ptr<IR> {compiler_class_name}::compile(const std::string &src, std::shared_ptr<Accelerator> acc) {{
accelerator = acc;
return compile(src);
}}
std::shared_ptr<IR> {compiler_class_name}::compile(const std::string &src) {{
auto ir = xacc::getService<IRProvider>("gate")->createIR();
// TODO: Add kernel(s) to IR
return ir;
}}
const std::string {compiler_class_name}::translate(const std::string &bufferVariable, std::shared_ptr<Function> function) {{
// TODO: Implement this
return "";
}}
}}
}}
#ifndef IMPLS_{compiler_class_name_upper}_HPP
#define IMPLS_{compiler_class_name_upper}_HPP
#include "Compiler.hpp"
namespace xacc {{
namespace quantum {{
class {compiler_class_name} : public xacc::Compiler {{
public:
{compiler_class_name}();
virtual std::shared_ptr<xacc::IR> compile(const std::string &src, std::shared_ptr<Accelerator> acc);
virtual std::shared_ptr<xacc::IR> compile(const std::string &src);
virtual const std::string translate(const std::string &bufferVariable, std::shared_ptr<Function> function);
virtual const std::string name() const {{
return "{compiler_class_name_lower}";
}}
virtual const std::string description() const {{
// TODO: Write a description of the compiler here
return "";
}}
virtual ~{compiler_class_name}() {{}}
}};
}}
}}
#endif
#include <gtest/gtest.h>
using namespace xacc;
using namespace xacc::quantum;
TEST({compiler_class_name}Tester, emptyTest) {{
xacc::Initialize();
const std::string src("__qpu__ example(AcceleratorBuffer qreg) {{\n"
"}}\n");
auto compiler = std::make_shared<{compiler_class_name}>();
auto ir = compiler->compile(src);
auto function = ir->getKernel("example");
std::cout << "HELLO\n" << function->toString("qreg") << "\n";
EXPECT_TRUE(ir->getKernels().size() == 1);
EXPECT_TRUE(function->nInstructions() == 0);
}}
int main(int argc, char** argv) {{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}}
\ No newline at end of file
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project({lib_name} LANGUAGES CXX)
option({project_name_upper}_BUILD_TESTS "Build test programs" OFF)
set(CMAKE_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
message(STATUS "C++ version ${{CXX_STANDARD}} configured.")
find_package(XACC REQUIRED)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set (CMAKE_INSTALL_PREFIX "${{XACC_ROOT}}" CACHE PATH "default install path" FORCE )
endif()
set(CppMicroServicesConfig_DIR "${{XACC_ROOT}}/share/cppmicroservices4/cmake")
set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} "${{XACC_ROOT}}/share/xacc")
set(CMAKE_MODULE_PATH ${{CMAKE_MODULE_PATH}} "${{CppMicroServicesConfig_DIR}}")
include(tests)
include(CppMicroServicesConfig)
include_directories(${{XACC_INCLUDE_DIRS}})
link_directories(${{XACC_LIBRARY_DIR}})
# TODO: add_subdirectory for each plugin
# add_subdirectory(compiler)
if(PYTHON_INCLUDE_DIR)
add_subdirectory(python)
endif()
if({project_name_upper}_BUILD_TESTS)
# TODO: include_directories for each plugin
# include_directories(${{CMAKE_SOURCE_DIR}}/compiler)
add_subdirectory(tests)
endif()
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
include_directories(${{PYTHON_INCLUDE_DIR}})
include_directories(${{XACC_ROOT}}/include/pybind11/include)
set (CMAKE_CXX_FLAGS "${{CMAKE_CXX_FLAGS}} -fno-strict-aliasing -O2 -g -pipe -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wformat -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv")
if(APPLE)
set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
endif(APPLE)
add_library(py{lib_name_alpha} SHARED {lib_name}-py.cpp)
set_target_properties(py{lib_name_alpha} PROPERTIES PREFIX "")
if(APPLE)
set_target_properties(py{lib_name_alpha} PROPERTIES INSTALL_RPATH "@loader_path/lib")
set_target_properties(py{lib_name_alpha} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(py{lib_name_alpha} PROPERTIES INSTALL_RPATH "$ORIGIN/lib")
set_target_properties(py{lib_name_alpha} PROPERTIES LINK_FLAGS "-shared")
endif()
install(TARGETS py{lib_name_alpha} DESTINATION ${{CMAKE_INSTALL_PREFIX}})
#include "XACC.hpp"
#include <pybind11/pybind11.h>
PYBIND11_MODULE(py{lib_name_alpha}, m) {{
m.doc() = "Python bindings for XACC. XACC provides a plugin infrastructure for "
"programming, compiling, and executing quantum kernels in a language and "
"hardware agnostic manner.";
}}
#! /usr/bin/env python3
import os
import re
import sys
import sysconfig
import platform
import subprocess
import multiprocessing
import site
from distutils.version import LooseVersion
from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext
from setuptools.command.install import install as InstallCommandBase
from setuptools.command.test import test as TestCommand
from shutil import copyfile, copymode
import shutil
import sysconfig
env = os.environ.copy()
class CMakeExtension(Extension):
def __init__(self, name, sourcedir=''):
Extension.__init__(self, name, sources=[])
self.sourcedir = os.path.abspath(sourcedir)
class CMakeBuild(build_ext):
def run(self):
try:
out = subprocess.check_output(['cmake', '--version'])
except OSError:
raise RuntimeError(
"CMake must be installed to build the following extensions: " +
", ".join(e.name for e in self.extensions))
if platform.system() == "Windows":
cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)',
out.decode()).group(1))
if cmake_version < '3.1.0':
raise RuntimeError("CMake >= 3.1.0 is required on Windows")
for ext in self.extensions:
self.build_extension(ext)
def build_extension(self, ext):
extdir = os.path.abspath(
os.path.dirname(self.get_ext_fullpath(ext.name)))
script_path = os.path.dirname(os.path.realpath(__file__))
install_prefix = script_path + '/' + self.build_lib + '/xacc'
print(dir(self))
print(self.build_lib)
import pyxacc
cmake_args = ['-DPYTHON_INCLUDE_DIR=' + sysconfig.get_paths()['platinclude'],
'-DXACC_DIR='+os.path.dirname(os.path.realpath(pyxacc.__file__)),
'-DFROM_SETUP_PY=TRUE']
args = sys.argv[1:]
if 'install' not in args:
cmake_args.append('-DCMAKE_INSTALL_PREFIX='+install_prefix) #install_prefix = script_path + '/' + self.build_lib
cfg = 'Debug' if self.debug else 'Release'
build_args = ['--config', cfg]
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
build_args += ['--', '-j'+str(multiprocessing.cpu_count())]
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
subprocess.check_call(['cmake', ext.sourcedir] + cmake_args,
cwd=self.build_temp, env=env)
subprocess.check_call(['cmake', '--build', '.', '--target', 'install'] + build_args,
cwd=self.build_temp)
print() # Add an empty line for cleaner output
s = setup(
name='{lib_name}',
version='0.1',
author='',
install_requires=['xacc >= 0.1.2'],
author_email='',
packages=find_packages('python'),
package_dir={{'':'python'}},
description='Generated XACC plugins project',
long_description='XACC provides a language and hardware agnostic programming framework for hybrid classical-quantum applications.',
ext_modules=[CMakeExtension('py{lib_name_alpha}')],
cmdclass={{'build_ext':CMakeBuild}},# 'install':InstallCommand}},
zip_safe=False
)
# add_xacc_test(ExampleCompiler) # This would add tests located in ExampleCompilerTester.cpp