2015-07-22 07:49:06 +08:00
#!/usr/bin/env python
import argparse
import os , sys
import re
import datetime as dt
# python 3 compatibility
try :
import cStringIO as sstream
except ImportError :
2016-03-13 22:03:05 +08:00
from io import StringIO
2015-07-22 07:49:06 +08:00
description = " Converts sol to a single file for convenience. "
# command line parser
parser = argparse . ArgumentParser ( usage = ' %(prog)s [options...] ' , description = description )
2017-12-09 15:52:08 +08:00
parser . add_argument ( ' --output ' , ' -o ' , nargs = ' + ' , help = ' name and location of where to place file (and forward declaration file) ' , metavar = ' file ' , default = ' sol.hpp ' )
2015-07-22 07:49:06 +08:00
parser . add_argument ( ' --quiet ' , help = ' suppress all output ' , action = ' store_true ' )
args = parser . parse_args ( )
2017-12-09 15:52:08 +08:00
single_file = ' '
forward_single_file = ' '
single_file = args . output [ 0 ]
if len ( args . output ) > 1 :
forward_single_file = args . output [ 1 ]
else :
a , b = os . path . splitext ( single_file )
forward_single_file = a + ' _forward ' + b
2015-07-22 07:49:06 +08:00
script_path = os . path . normpath ( os . path . dirname ( os . path . realpath ( __file__ ) ) )
working_dir = os . getcwd ( )
os . chdir ( script_path )
intro = """ // The MIT License (MIT)
2017-05-15 22:41:50 +08:00
/ / Copyright ( c ) 2013 - 2017 Rapptz , ThePhD and contributors
2015-07-22 07:49:06 +08:00
/ / Permission is hereby granted , free of charge , to any person obtaining a copy of
/ / this software and associated documentation files ( the " Software " ) , to deal in
/ / the Software without restriction , including without limitation the rights to
/ / use , copy , modify , merge , publish , distribute , sublicense , and / or sell copies of
/ / the Software , and to permit persons to whom the Software is furnished to do so ,
/ / subject to the following conditions :
/ / The above copyright notice and this permission notice shall be included in all
/ / copies or substantial portions of the Software .
/ / THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
/ / IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY , FITNESS
/ / FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR
/ / COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER
/ / IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
/ / CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
/ / This file was generated with a script .
/ / Generated { time } UTC
/ / This header was generated with sol { version } ( revision { revision } )
2016-03-12 07:41:44 +08:00
/ / https : / / github . com / ThePhD / sol2
2015-07-22 07:49:06 +08:00
#ifndef {guard}
#define {guard}
"""
module_path = os . path . join ( script_path )
includes = set ( [ ] )
standard_include = re . compile ( r ' #include <(.*?)> ' )
2017-09-10 09:38:13 +08:00
local_include = re . compile ( r ' #( \ s*?)include " (.*?) " ' )
2015-07-22 07:49:06 +08:00
ifndef_cpp = re . compile ( r ' #ifndef SOL_.*?_HPP ' )
define_cpp = re . compile ( r ' #define SOL_.*?_HPP ' )
endif_cpp = re . compile ( r ' #endif // SOL_.*?_HPP ' )
def get_include ( line , base_path ) :
local_match = local_include . match ( line )
if local_match :
# local include found
2017-09-10 09:38:13 +08:00
full_path = os . path . normpath ( os . path . join ( base_path , local_match . group ( 2 ) ) ) . replace ( ' \\ ' , ' / ' )
2015-07-22 07:49:06 +08:00
return full_path
return None
def is_include_guard ( line ) :
return ifndef_cpp . match ( line ) or define_cpp . match ( line ) or endif_cpp . match ( line )
def get_revision ( ) :
return os . popen ( ' git rev-parse --short HEAD ' ) . read ( ) . strip ( )
def get_version ( ) :
return os . popen ( ' git describe --tags --abbrev=0 ' ) . read ( ) . strip ( )
def process_file ( filename , out ) :
global includes
filename = os . path . normpath ( filename )
2016-08-18 02:26:26 +08:00
relativefilename = filename . replace ( script_path + os . sep , " " ) . replace ( " \\ " , " / " )
2015-07-22 07:49:06 +08:00
if filename in includes :
return
includes . add ( filename )
if not args . quiet :
print ( ' processing {} ' . format ( filename ) )
2016-03-13 22:03:05 +08:00
out . write ( ' // beginning of {} \n \n ' . format ( relativefilename ) )
2015-07-22 07:49:06 +08:00
empty_line_state = True
2016-03-13 22:03:05 +08:00
with open ( filename , ' r ' , encoding = ' utf-8 ' ) as f :
2015-07-22 07:49:06 +08:00
for line in f :
# skip comments
if line . startswith ( ' // ' ) :
continue
# skip include guard non-sense
if is_include_guard ( line ) :
continue
# get relative directory
base_path = os . path . dirname ( filename )
# check if it's a standard file
std = standard_include . search ( line )
if std :
std_file = os . path . join ( ' std ' , std . group ( 0 ) )
if std_file in includes :
continue
includes . add ( std_file )
# see if it's an include file
name = get_include ( line , base_path )
if name :
process_file ( name , out )
continue
empty_line = len ( line . strip ( ) ) == 0
if empty_line and empty_line_state :
continue
empty_line_state = empty_line
# line is fine
out . write ( line )
2016-03-13 22:03:05 +08:00
out . write ( ' // end of {} \n \n ' . format ( relativefilename ) )
2015-07-22 07:49:06 +08:00
version = get_version ( )
revision = get_revision ( )
include_guard = ' SOL_SINGLE_INCLUDE_HPP '
2017-12-09 15:52:08 +08:00
forward_include_guard = ' SOL_SINGLE_INCLUDE_FORWARD_HPP '
2015-07-22 07:49:06 +08:00
2016-12-16 13:31:45 +08:00
processed_files = [ os . path . join ( script_path , x ) for x in [ ' sol.hpp ' ] ]
2017-12-09 15:52:08 +08:00
forward_processed_files = [ os . path . join ( script_path , x ) for x in [ ' sol/forward.hpp ' ] ]
2015-07-22 07:49:06 +08:00
result = ' '
2017-12-09 15:52:08 +08:00
forward_result = ' '
if not args . quiet :
print ( ' Current version: {version} (revision {revision} ) \n ' . format ( version = version , revision = revision ) )
print ( ' Creating single header for sol ' )
2015-07-22 07:49:06 +08:00
2016-03-13 22:03:05 +08:00
ss = StringIO ( )
2015-07-22 07:49:06 +08:00
ss . write ( intro . format ( time = dt . datetime . utcnow ( ) , revision = revision , version = version , guard = include_guard ) )
for processed_file in processed_files :
process_file ( processed_file , ss )
ss . write ( ' #endif // {} \n ' . format ( include_guard ) )
result = ss . getvalue ( )
ss . close ( )
2017-12-09 15:52:08 +08:00
if not args . quiet :
print ( ' finished creating single header for sol \n ' )
if not args . quiet :
print ( ' Creating single forward declaration header for sol ' )
includes = set ( [ ] )
forward_ss = StringIO ( )
forward_ss . write ( intro . format ( time = dt . datetime . utcnow ( ) , revision = revision , version = version , guard = forward_include_guard ) )
for forward_processed_file in forward_processed_files :
process_file ( forward_processed_file , forward_ss )
forward_ss . write ( ' #endif // {} \n ' . format ( forward_include_guard ) )
forward_result = forward_ss . getvalue ( )
forward_ss . close ( )
if not args . quiet :
print ( ' finished creating single forward declaration header for sol \n ' )
with open ( single_file , ' w ' , encoding = ' utf-8 ' ) as f :
2017-12-11 04:56:49 +08:00
if not args . quiet :
print ( ' writing {} ... ' . format ( single_file ) )
2015-07-22 07:49:06 +08:00
f . write ( result )
2017-12-09 15:52:08 +08:00
with open ( forward_single_file , ' w ' , encoding = ' utf-8 ' ) as f :
2017-12-11 04:56:49 +08:00
if not args . quiet :
print ( ' writing {} ... ' . format ( single_file ) )
2017-12-09 15:52:08 +08:00
f . write ( forward_result )