Initial CMake Support + macOS support (not final)

This commit is contained in:
Sam Fuller
2019-01-04 02:52:48 -07:00
parent f700d605a0
commit 91c4461b05
11 changed files with 638 additions and 148 deletions
+5
View File
@@ -0,0 +1,5 @@
.idea
.dew
dist
__pycache__
codegen.egg-info
+80
View File
@@ -0,0 +1,80 @@
cmake_minimum_required(VERSION 3.12)
include(CMakePackageConfigHelpers)
project(codegen VERSION 0.1.0)
find_package(PythonInterp 3.6 REQUIRED)
add_library(codegen INTERFACE)
target_compile_definitions(
codegen
INTERFACE
WITH_CODEGEN
)
add_custom_target(
codegen_sdist
ALL
COMMAND
"${PYTHON_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/setup.py" "sdist" "-d" "${PROJECT_BINARY_DIR}/dist"
WORKING_DIRECTORY
"${PROJECT_SOURCE_DIR}"
)
add_dependencies(codegen codegen_sdist)
# Install the CMake Module
install(
DIRECTORY "${PROJECT_SOURCE_DIR}/cmake"
DESTINATION "share"
)
# Install the python package
install(
FILES "${PROJECT_BINARY_DIR}/dist/codegen-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.tar.gz"
DESTINATION "share/codegen/"
)
# Install the project headers
install(
DIRECTORY "${PROJECT_SOURCE_DIR}/include/codegen"
DESTINATION "include/codegen"
)
set(version_config_file "${PROJECT_BINARY_DIR}/codegenConfigVersion.cmake")
set(config_file "${PROJECT_BINARY_DIR}/codegenConfig.cmake")
set(config_install_dir "lib/cmake/codegen")
# Associate target with export
install(
TARGETS codegen
EXPORT codegenTargets
INCLUDES DESTINATION "include/codegen"
)
# Install the target config files
install(
EXPORT codegenTargets
NAMESPACE "codegen::"
DESTINATION "${config_install_dir}"
)
# Generate version config file
write_basic_package_version_file(
"${version_config_file}"
COMPATIBILITY SameMajorVersion
)
# Generate config file
configure_package_config_file(
"Config.cmake.in"
"${config_file}"
INSTALL_DESTINATION "lib/cmake/codegen"
)
# Install the config files
install(
FILES "${config_file}" "${version_config_file}"
DESTINATION ${config_install_dir}
)
+4
View File
@@ -0,0 +1,4 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/codegenTargets.cmake")
check_required_components(codegen)
+217
View File
@@ -0,0 +1,217 @@
cmake_minimum_required(VERSION 3.12)
function(add_codegen_targets
source_files
generated_files_var
input_root
output_root
include_directories
)
#
# Find our python interpreter, and set up some python related variables.
#
find_package(PythonInterp 3.6 REQUIRED)
set(venv_path "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv")
set(venv_dummy "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv_dummy")
set(package_dummy "${CMAKE_CURRENT_BINARY_DIR}/codegen_package_dummy")
set(missing_requirements FALSE)
#
# Find libclang.
#
find_library(CLANG_LIBRARY NAMES clang libclang REQUIRED)
if ("${CLANG_LIBRARY}" STREQUAL "CLANG_LIBRARY-NOTFOUND")
message(SEND_ERROR "libclang not found")
set(missing_requirements TRUE)
endif()
#
# Find the codegen python package file
#
if ("${CODEGEN_PACKAGE}" STREQUAL "")
foreach (prefix ${CMAKE_PREFIX_PATH})
set(codegen_package_candidate "${prefix}/share/codegen/codegen-0.1.0.tar.gz")
if (EXISTS "${codegen_package_candidate}")
set(CODEGEN_PACKAGE "${codegen_package_candidate}")
break()
endif()
endforeach()
if ("${CODEGEN_PACKAGE}" STREQUAL "")
set(CODEGEN_PACKAGE "CODEGEN_PACKAGE-NOTFOUND" CACHE FILEPATH)
endif()
endif()
if ("${CODEGEN_PACKAGE}" STREQUAL "CODEGEN_PACKAGE-NOTFOUND")
message(SEND_ERROR "codegen package not found")
set(missing_requirements TRUE)
endif()
if (missing_requirements)
message(FATAL_ERROR "Missing requirements")
endif()
#
# Get name of python executable. We gotta add a '.exe' prefix if we're on windows, obviously.
#
if (WIN32)
set(sep ";")
set(python_executable_name "python.exe")
else()
set(sep ":")
set(python_executable_name "python")
endif()
#
# Determine the path of the virtual env python wrapper. It's different on Windows.
#
set(venv_python_executable_path "bin/${python_executable_name}")
if (NOT EXISTS "${venv_python_executable_path}" AND WIN32)
set(venv_python_executable_path "Scripts/${python_executable_name}")
endif()
#
# Setup the virtual env for the codegen tool to use if it hasn't been set up.
#
if (NOT EXISTS "${venv_dummy}")
message(STATUS "Creating virtual env at ${venv_path}")
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -m ensurepip
RESULT_VARIABLE update_venv_result
OUTPUT_VARIABLE update_venv_output
ERROR_VARIABLE update_venv_error
)
if (NOT update_venv_result EQUAL 0)
# ensurepip module failed not installed. Check if pip is installed, and cause an error if it's not installed.
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -m pip --version
RESULT_VARIABLE pip_version_result
)
if (NOT pip_version_result EQUAL 0)
message(FATAL_ERROR "Failed to run ensurepip module, and pip is not installed. Please install pip manually.")
endif()
endif()
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -m pip install virtualenv
RESULT_VARIABLE update_venv_result
OUTPUT_VARIABLE update_venv_output
ERROR_VARIABLE update_venv_error
)
if (NOT update_venv_result EQUAL 0)
message(FATAL_ERROR "Failed to install virtualenv with pip: result: ${update_venv_result}. stderr:\n${update_venv_error}")
endif()
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" -m virtualenv "${venv_path}"
RESULT_VARIABLE update_venv_result
OUTPUT_VARIABLE update_venv_output
ERROR_VARIABLE update_venv_error
)
if (NOT update_venv_result EQUAL 0)
message(FATAL_ERROR "Cannot update codegen tool venv: result: ${update_venv_result}. stderr:\n${update_venv_error}")
endif()
#
# Install the codegen package with pip
#
execute_process(
COMMAND
"${venv_path}/${venv_python_executable_path}" "-m" "pip"
"install" "${CODEGEN_PACKAGE}"
RESULT_VARIABLE pip_result
ERROR_VARIABLE pip_error
)
if (NOT pip_result EQUAL 0)
message(FATAL_ERROR "Failed to install codegen packages into codegen virtualenv. result: ${pip_result}. stderr:\n${pip_error}")
endif()
file(TOUCH "${package_dummy}")
#
# Create the dummy file to signify that we have successfully created the venv.
#
file(TOUCH "${venv_dummy}")
endif()
#
# Add build-time target to update the codegen package if it's touched.
#
add_custom_command(
OUTPUT
"${package_dummy}"
COMMAND
"${venv_path}/${venv_python_executable_path}" "-m" "pip"
"install" "${CODEGEN_PACKAGE}"
COMMAND
"${CMAKE_COMMAND}" "-E" "touch" "${package_dummy}"
DEPENDS
"${CODEGEN_PACKAGE}"
)
set(include_directories_arguments "")
foreach(include_directory include_directories)
list(APPEND include_directories_arguments "-I")
list(APPEND include_directories_arguments "${include_directory}")
endforeach()
message(STATUS "Updating codegen targets")
#
# Set up targets for all files which will be generated by the codegen tool.
#
set(all_output_files "")
foreach(current_source_file ${source_files})
#
# Determine which files are generated by this source file at configure time
#
execute_process(
COMMAND
"${venv_path}/${venv_python_executable_path}" "-m" "codegen"
"get_output_files"
"${current_source_file}"
${include_directories_arguments}
"--libclangpath" "${CLANG_LIBRARY}"
"--source-root" "${input_root}"
"--output-root" "${output_root}"
OUTPUT_VARIABLE current_output_files
ERROR_VARIABLE tool_error
RESULT_VARIABLE tool_result
)
if (NOT tool_result EQUAL 0)
message(SEND_ERROR "Error running codegen tool. result: ${tool_result}. stderr:\n${tool_error}")
continue()
endif()
#
# Set up a build target for the outputs given to us by the above commands.
#
string(STRIP "${current_output_files}" current_output_files)
list(LENGTH current_output_files current_output_files_len)
if ("${current_output_files_len}" EQUAL 0)
continue()
endif()
foreach(current_output_file ${current_output_files})
list(APPEND all_output_files "${current_output_file}")
endforeach()
add_custom_command(
OUTPUT "${current_output_files}"
COMMAND
"${venv_path}/${venv_python_executable_path}" "-m" "codegen"
"generate"
"${current_source_file}"
${include_directories_arguments}
"--libclangpath" "${CLANG_LIBRARY}"
"--source-root" "${input_root}"
"--output-root" "${output_root}"
DEPENDS "${current_source_file}" "${package_dummy}"
)
endforeach()
#
# "Return" a list of all files that will be generated during build time.
#
set("${generated_files_var}" "${all_output_files}" PARENT_SCOPE)
endfunction()
View File
+3
View File
@@ -0,0 +1,3 @@
import codegen.cli
exit(codegen.cli.main())
+50
View File
@@ -0,0 +1,50 @@
import sys
import argparse
from typing import List
from codegen import codegen
class ArgumentData(object):
def __init__(self) -> None:
self.command = ''
self.source_file = ''
self.libclangpath = ''
self.include_paths: List[str] = []
self.source_root = ''
self.output_root = ''
argparser = argparse.ArgumentParser()
argparser.add_argument('command', help='What to do')
argparser.add_argument('source_file', help='Source file to use')
argparser.add_argument('--libclangpath', help='Path to libclang library file', required=True)
argparser.add_argument('--include', '-I', help='Define an include path', dest='include_paths', action='append')
argparser.add_argument('--source-root', help='Root path of all source files', required=True)
argparser.add_argument('--output-root', help='Root path of all files to be output', required=True)
def main() -> int:
args = ArgumentData()
# noinspection PyTypeChecker
argparser.parse_args(namespace=args)
if args.command.lower() == 'get_output_files':
return do_get_output_files_command(args)
if args.command.lower() == 'generate':
return do_generate_command(args)
sys.stderr.write('Invalid Command\n')
return 1
def do_get_output_files_command(args: ArgumentData) -> int:
output_files = codegen.get_output_files(args.source_file, args.include_paths, args.libclangpath, args.source_root, args.output_root)
sys.stdout.write(';'.join(output_files))
return 0
def do_generate_command(args: ArgumentData) -> int:
codegen.RunCodegen(args.source_file, args.include_paths, args.libclangpath, args.source_root, args.output_root)
return 0
+48 -127
View File
@@ -1,13 +1,13 @@
# C++ code generation using clang
import clang.cindex
import cProfile
import glob
import mako.template
import os
import sys
from typing import List, Iterable
# Directory that the codegen script file is stored in
ScriptDir = os.path.dirname(__file__)
TemplateDir = os.path.normpath(os.path.join(os.path.dirname(__file__), 'data'))
# [debug] Whether to enable profiling
EnableProfiling = False
@@ -16,10 +16,10 @@ EnableProfiling = False
PrintAST = False
# [debug] Path to store auto-generated codegen source files
ExportPath = "build\\codegen"
ExportPath = "build/codegen"
# [debug] Path to store the final output cpp file
OutputCppSource = "%s\\auto_codegen.cpp" % ExportPath
OutputCppSource = "%s/auto_codegen.cpp" % ExportPath
# [debug] Path to find the source files
SourceRoot = "."
@@ -33,6 +33,7 @@ InputViaCommandLine = True
# Whether to always do a full regen
ForceFullRegen = False
def GetCursorFullyQualifiedName(Cursor):
""" Return the fully qualified name of the object represented by Cursor, including any parent scopes """
OutName = Cursor.spelling
@@ -150,7 +151,7 @@ class ScopedDeclare:
def DebugPrint(self):
print( self.GenerateText(0) )
class SourceFile:
""" A C++ source code file """
def __init__(self, FilePath):
@@ -158,17 +159,17 @@ class SourceFile:
self.Enums = []
self.RootDeclare = ScopedDeclare("", "")
def GetCodegenFile(self):
def GetCodegenFile(self, SourceRoot: str, OutputRoot: str):
""" Returns the path to store the auto-generated code for this source file """
if os.path.isabs(self.FilePath):
RelativePath = self.FilePath[3:]
return "%s\\%s.codegen.inl" % (ExportPath, RelativePath)
else:
return "%s\\%s.codegen.inl" % (ExportPath, self.FilePath)
abspath = os.path.abspath(self.FilePath)
relpath = os.path.relpath(abspath, SourceRoot)
reldir, filename = os.path.split(relpath)
filename_no_ext, _ = os.path.splitext(filename)
return os.path.join(OutputRoot, reldir, filename_no_ext + '_codegen.cpp')
def LastModifiedTime(self):
""" Returns the last modified time for this source file """
return os.path.getmtime( self.FilePath )
return os.path.getmtime(self.FilePath)
def Analyze(self, ClangIndex, CompileEnvironment):
""" Analyzes the AST for any components that need generated code """
@@ -179,23 +180,21 @@ class SourceFile:
if PrintAST:
DebugPrintCursorRecursive(TranslationUnit.cursor, self.FilePath)
print("")
# Generate code
def Generate(self, OutputPath: str):
if self.Enums:
MakoTemplateFile = open("%s/template.mako" % ScriptDir, "r")
MakoTemplateText = MakoTemplateFile.read()
MakoTemplateFile.close()
with open("%s/template.mako" % TemplateDir, "r") as MakoTemplateFile:
MakoTemplateText = MakoTemplateFile.read()
MakoTemplate = mako.template.Template(MakoTemplateText)
GeneratedCode = MakoTemplate.render(Enums=self.Enums, IncludeFile=self.FilePath, ForwardDeclares=self.RootDeclare.Children)
OutPath = self.GetCodegenFile()
OutDir = os.path.dirname(OutPath)
GeneratedCode = MakoTemplate.render(Enums=self.Enums, IncludeFile=self.FilePath,
ForwardDeclares=self.RootDeclare.Children)
OutDir = os.path.dirname(OutputPath)
os.makedirs(OutDir, exist_ok=True)
OutCodegenFile = open(OutPath, "w")
OutCodegenFile.write(GeneratedCode)
OutCodegenFile.close()
with open(OutputPath, "w") as file:
file.write(GeneratedCode)
def CursorRecurse(self, Cursor, Depth):
""" Recursive function that performs the actual analysis work of the AST """
@@ -248,114 +247,36 @@ class SourceFile:
else:
self.CursorRecurse(Child, Depth + 1)
def RunCodegen():
# Source files to parse
SourceFiles = []
IncludePaths = []
OutCodegenSource = ""
if ParseCmdLine:
global InputViaCommandLine
for i in range(0, len(sys.argv)):
arg = sys.argv[i]
if InputViaCommandLine is True and arg == "-sourcefiles" or arg == "-include":
i += 1
while i < len(sys.argv) and sys.argv[i][0] != '-':
File = sys.argv[i]
if arg == "-sourcefiles":
# this isn't the best way to handle this since the output file is provided via commandline arg
if "auto_codegen" not in File:
SourceFiles.append(File)
else:
IncludePaths.append(File)
i += 1
i -= 1
# The only time we don't use commandline input is for debugging
if arg == "-cmdinput":
InputViaCommandLine = True
if arg == "-full":
global ForceFullRegen
ForceFullRegen = True
if arg == "-o":
i += 1
OutCodegenSource = sys.argv[i]
global ExportPath
ExportPath = os.path.dirname(OutCodegenSource)
if arg == "-pwd":
i += 1
WorkingDirectory = sys.argv[i]
os.chdir(WorkingDirectory)
if not InputViaCommandLine:
SourceFiles = glob.glob("%s\\**\\*.cpp" % SourceRoot, recursive=True)
SourceFiles += glob.glob("%s\\**\\*.hpp" % SourceRoot, recursive=True)
SourceFiles += glob.glob("%s\\**\\*.h" % SourceRoot, recursive=True)
OutCodegenSource = OutputCppSource
print("Codegen Input: " + " ".join(SourceFiles))
print("Build Dir: " + ExportPath)
def RunCodegen(file_path: str, include_paths: Iterable[str], lib_clang_path: str, source_root: str, output_root: str):
file = GetAnalyzedSourceFile(file_path, include_paths, lib_clang_path)
output_path = file.GetCodegenFile(source_root, output_root)
file.Generate(output_path)
# if EnableProfiling:
# cProfile.run('RunCodegen()')
# else:
# RunCodegen()
def GetAnalyzedSourceFile(FilePath: str, IncludePaths: Iterable[str], LibClangPath: str) -> SourceFile:
# Clang index
#@todo - this definitely isn't portable??? how should I be setting this???
clang.cindex.Config.set_library_file('C:\\Program Files\\LLVM\\bin\\libclang.dll')
clang.cindex.Config.set_library_file(LibClangPath)
ClangIndex = clang.cindex.Index.create()
# C++ environment
CompileEnvironment = CxxCompileEnvironment(IncludePaths)
# Process all source files
LastRegenTime = os.path.getmtime(OutCodegenSource) if os.path.isfile(OutCodegenSource) else 0
OutFiles = []
NewFile = SourceFile(FilePath)
NewFile.Analyze(ClangIndex, CompileEnvironment)
return NewFile
for FilePath in SourceFiles:
# If the file doesn't exist, just skip it.
# This mirrors qmake behavior.
if not os.path.isfile(FilePath):
continue
NewFile = SourceFile(FilePath)
NewFileOut = NewFile.GetCodegenFile()
# Only run codegen on this file if it has been modified since last time
if ForceFullRegen or NewFile.LastModifiedTime() > LastRegenTime:
NewFile.Analyze(ClangIndex, CompileEnvironment)
if NewFile.Enums:
# Register this as a file that needs to be included in the output source
OutFiles.append(NewFileOut)
else:
# Delete codegen file if it exists
if os.path.isfile(NewFileOut):
os.remove(NewFileOut)
# If the file hasn't been modified, we still want to make sure it gets included in the output source
else:
if os.path.isfile(NewFileOut):
OutFiles.append(NewFileOut)
# Create final output cpp
OutDir = os.path.dirname(OutCodegenSource)
os.makedirs(OutDir, exist_ok=True)
def get_output_files(source_file: str, include_paths: Iterable[str], lib_clang_path: str, source_root: str, output_root: str) -> List[str]:
file = GetAnalyzedSourceFile(source_file, include_paths, lib_clang_path)
OutFile = open(OutCodegenSource, "w")
OutFile.write("#pragma warning( push )\n")
OutFile.write("#pragma warning( disable : 4146 )\n") # Suppress C4146: unary minus operator applied to unsigned type, result still unsgined
[OutFile.write("#include \"%s\"\n" % os.path.normpath(CodegenFile)) for CodegenFile in OutFiles]
OutFile.write("#pragma warning( pop )\n")
OutFile.close()
if not file.Enums:
return []
if EnableProfiling:
cProfile.run('RunCodegen()')
else:
RunCodegen()
return [file.GetCodegenFile(source_root, output_root)]
+30
View File
@@ -0,0 +1,30 @@
% if Enums:
#include <codegen/EnumReflection.h>
% endif
#include "${IncludeFile}"
#pragma warning( push )
#pragma warning( disable : 4146 ) // Suppress C4146: unary minus operator applied to unsigned type, result still unsgined
## % for Decl in ForwardDeclares:
## ${Decl.GenerateText(0)}
## % endfor
% for Enum in Enums:
template <>
const CEnumNameMap TEnumReflection<${Enum.FullName}>::skNameMap = {
<% ValueSet = set() %> \
% for Constant in Enum.Constants:
% if Constant.Value not in ValueSet:
{ ${Constant.Value}, "${Constant.Name}" },
<% ValueSet.add(Constant.Value) %> \
% endif
% endfor
};
template <>
const int TEnumReflection<${Enum.FullName}>::skErrorValue = ${Enum.ErrorValue};
% endfor
#pragma warning( pop )
+201
View File
@@ -0,0 +1,201 @@
"""A setuptools based setup module.
See:
https://packaging.python.org/en/latest/distributing.html
https://github.com/pypa/sampleproject
"""
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
from os import path
# io.open is needed for projects that support Python 2.7
# It ensures open() defaults to text mode with universal newlines,
# and accepts an argument to specify the text encoding
# Python 3 only projects can skip this import
from io import open
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
# Arguments marked as "Required" below must be included for upload to PyPI.
# Fields marked as "Optional" may be commented out.
setup(
# This is the name of your project. The first time you publish this
# package, this name will be registered for you. It will determine how
# users can install this project, e.g.:
#
# $ pip install sampleproject
#
# And where it will live on PyPI: https://pypi.org/project/sampleproject/
#
# There are some restrictions on what makes a valid project name
# specification here:
# https://packaging.python.org/specifications/core-metadata/#name
name='codegen', # Required
# Versions should comply with PEP 440:
# https://www.python.org/dev/peps/pep-0440/
#
# For a discussion on single-sourcing the version across setup.py and the
# project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='0.1.0', # Required
# This is a one-line description or tagline of what your project does. This
# corresponds to the "Summary" metadata field:
# https://packaging.python.org/specifications/core-metadata/#summary
# description='A sample Python project', # Optional
# This is an optional longer description of your project that represents
# the body of text which users will see when they visit PyPI.
#
# Often, this is the same as your README, so you can just read it in from
# that file directly (as we have already done above)
#
# This field corresponds to the "Description" metadata field:
# https://packaging.python.org/specifications/core-metadata/#description-optional
long_description=long_description, # Optional
# Denotes that our long_description is in Markdown; valid values are
# text/plain, text/x-rst, and text/markdown
#
# Optional if long_description is written in reStructuredText (rst) but
# required for plain-text or Markdown; if unspecified, "applications should
# attempt to render [the long_description] as text/x-rst; charset=UTF-8 and
# fall back to text/plain if it is not valid rst" (see link below)
#
# This field corresponds to the "Description-Content-Type" metadata field:
# https://packaging.python.org/specifications/core-metadata/#description-content-type-optional
long_description_content_type='text/markdown', # Optional (see note above)
# This should be a valid link to your project's main homepage.
#
# This field corresponds to the "Home-Page" metadata field:
# https://packaging.python.org/specifications/core-metadata/#home-page-optional
url='https://github.com/arukibree/CodeGen', # Optional
# This should be your name or the name of the organization which owns the
# project.
author='arukibree', # Optional
# This should be a valid email address corresponding to the author listed
# above.
# author_email='pypa-dev@googlegroups.com', # Optional
# Classifiers help users find your project by categorizing it.
#
# For a list of valid classifiers, see https://pypi.org/classifiers/
classifiers=[ # Optional
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
# Pick your license as you wish
'License :: OSI Approved :: MIT License',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
#'Programming Language :: Python :: 2',
#'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
# This field adds keywords for your project which will appear on the
# project page. What does your project relate to?
#
# Note that this is a string of words separated by whitespace, not a list.
# keywords='sample setuptools development', # Optional
# You can just specify package directories manually here if your project is
# simple. Or you can use find_packages().
#
# Alternatively, if you just want to distribute a single Python file, use
# the `py_modules` argument instead as follows, which will expect a file
# called `my_module.py` to exist:
#
# py_modules=["my_module"],
#
packages=find_packages(exclude=['contrib', 'docs', 'tests']), # Required
# This field lists other packages that your project depends on to run.
# Any package you put here will be installed by pip when your project is
# installed, so they must be valid existing projects.
#
# For an analysis of "install_requires" vs pip's requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=[
'clang==5.0',
'Mako==1.0.7'
],
# List additional groups of dependencies here (e.g. development
# dependencies). Users will be able to install these using the "extras"
# syntax, for example:
#
# $ pip install sampleproject[dev]
#
# Similar to `install_requires` above, these must be valid existing
# projects.
extras_require={ # Optional
'dev': [],
'test': [],
},
# If there are data files included in your packages that need to be
# installed, specify them here.
#
# If using Python 2.6 or earlier, then these have to be included in
# MANIFEST.in as well.
package_data={ # Optional
'codegen': ['data/*.mako'],
},
# Although 'package_data' is the preferred approach, in some case you may
# need to place data files outside of your packages. See:
# http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
#
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
# data_files=[('my_data', ['data/data_file'])], # Optional
# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# `pip` to create the appropriate form of executable for the target
# platform.
#
# For example, the following would provide a command called `sample` which
# executes the function `main` from this package when invoked:
# entry_points={ # Optional
# 'console_scripts': [
# 'sample=sample:main',
# ],
# },
# List additional URLs that are relevant to your project as a dict.
#
# This field corresponds to the "Project-URL" metadata fields:
# https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use
#
# Examples listed include a pattern for specifying where the package tracks
# issues, where the source is hosted, where to say thanks to the package
# maintainers, and where to support the project financially. The key is
# what's used to render the link text on PyPI.
# project_urls={ # Optional
# 'Bug Reports': 'https://github.com/pypa/sampleproject/issues',
# 'Funding': 'https://donate.pypi.org',
# 'Say Thanks!': 'http://saythanks.io/to/example',
# 'Source': 'https://github.com/pypa/sampleproject/',
# },
)
-21
View File
@@ -1,21 +0,0 @@
% if Enums:
#include <codegen/EnumReflection.h>
% endif
% for Decl in ForwardDeclares:
${Decl.GenerateText(0)}
% endfor
% for Enum in Enums:
const CEnumNameMap TEnumReflection<enum ${Enum.FullName}>::skNameMap = {
<% ValueSet = set() %> \
% for Constant in Enum.Constants:
% if Constant.Value not in ValueSet:
{ ${Constant.Value}, "${Constant.Name}" },
<% ValueSet.add(Constant.Value) %> \
% endif
% endfor
};
const int TEnumReflection<enum ${Enum.FullName}>::skErrorValue = ${Enum.ErrorValue};
% endfor