Merge pull request #501 from yitam/buildscripts
Python scripts for building extensions for PHP 7+ in Windows
This commit is contained in:
commit
687f3a11f5
98
buildscripts/README.md
Normal file
98
buildscripts/README.md
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# Windows
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
To build extensions for
|
||||||
|
* PHP 7.0* or PHP 7.1*, install Visual Studio 2015 and make sure C++ tools are enabled.
|
||||||
|
* PHP 7.2*, install Visual Studio 2017, including Visual C++ toolset, the Windows SDK components, and Git for Windows.
|
||||||
|
|
||||||
|
To use the sample build scripts `builddrivers.py` and `buildtools.py`, install Python 3.x in Windows.
|
||||||
|
|
||||||
|
## Compile the drivers
|
||||||
|
|
||||||
|
You must first be able to build PHP 7.* without including these extensions. For help with doing this, see the [official PHP website](https://wiki.php.net/internals/windows/stepbystepbuild) for building PHP 7.0* or PHP 7.1* on Windows or [PHP SDK page](https://github.com/OSTC/php-sdk-binary-tools) for the new instructions for building PHP 7.2 and/or above.
|
||||||
|
|
||||||
|
The Microsoft Drivers for PHP for SQL Server have been compiled and tested with PHP 7.0.* and 7.1.* using the Visual C++ 2015 as well as PHP 7.2.0 beta using the Visual C++ 2017 v15.0.
|
||||||
|
|
||||||
|
### Manually building from source
|
||||||
|
|
||||||
|
1. Download the *source* directory from this repository
|
||||||
|
|
||||||
|
2. Make a copy of the *shared* folder as a subfolder in *sqlsrv* and/or *pdo_sqlsrv* folder
|
||||||
|
|
||||||
|
3. Copy the *sqlsrv* and/or *pdo_sqlsrv* folder(s) into the PHP source ext subdirectory
|
||||||
|
|
||||||
|
4. Run `buildconf --force` to rebuild the configure.js script to include the *sqlsrv* and/or *pdo_sqlsrv* driver(s).
|
||||||
|
|
||||||
|
5. Run `configure.bat` with the desired driver options (as shown below) to generate the makefile. You can run `configure.bat --help` to see what other options are available. For example, for non-thread safe build, add this option `--disable-zts`.
|
||||||
|
* For SQLSRV add: `--enable-sqlsrv=shared`
|
||||||
|
* For PDO_SQLSRV add: `--enable-pdo --with-pdo-sqlsrv=shared`
|
||||||
|
|
||||||
|
6. Run `nmake`. Optionally, you can run `nmake clean` first.
|
||||||
|
|
||||||
|
7. To install the drivers, there are two ways:
|
||||||
|
* Run `nmake install`, or
|
||||||
|
* Copy the drivers:
|
||||||
|
* Find the directory where the newly compiled `php.exe` is
|
||||||
|
* Locate the compiled php_sqlsrv.dll and/or php_pdo_sqlsrv.dll
|
||||||
|
* Copy the dll(s) to the `ext` subfolder
|
||||||
|
|
||||||
|
### Using the sample build scripts
|
||||||
|
|
||||||
|
The sample build scripts, `builddrivers.py` and `buildtools.py`, are expected to build our extensions for PHP in Windows.
|
||||||
|
|
||||||
|
#### Overview
|
||||||
|
|
||||||
|
When asked to provide the PHP version, you should enter values like `7.1.7`. If it's alpha, beta, or RC version, make sure the name you provide matches the PHP tag name without the prefix `php-`. For example, for PHP 7.2 beta 2, the tag name is `php-7.2.0beta2`, so you should enter `7.2.0beta2`. Visit [PHP SRC]( https://github.com/php/php-src) to find the appropriate tag names.
|
||||||
|
|
||||||
|
PHP recommends to unzip the PHP SDK into the shortest possible path, preferrably somewhere near the root drive. Therefore, this script will by default create a `php-sdk` folder in the C:\ drive, and this `php-sdk` directory tree will remain unless you remove it yourself. For ongoing development, we suggest you keep it around. The build scripts will handle updating the PHP SDK if a new version is available.
|
||||||
|
|
||||||
|
#### Steps
|
||||||
|
|
||||||
|
1. Launch a regular `cmd` prompt
|
||||||
|
|
||||||
|
2. Change to the directory where the Python scripts `builddrivers.py` and `buildtools.py` are
|
||||||
|
|
||||||
|
3. Interactive mode:
|
||||||
|
* Run `py builddrivers.py` to use the interactive mode. Use lower cases to answer the following questions:
|
||||||
|
* PHP Version (e.g. `7.1.7` or `7.2.0beta2`)
|
||||||
|
* 64-bit?
|
||||||
|
* Thread safe?
|
||||||
|
* Driver?
|
||||||
|
* Debug enabled?
|
||||||
|
* Download source from GitHub?
|
||||||
|
* For `yes/no` questions, you can simply hit `ENTER` key for `yes`. Other questions are self-explanatory.
|
||||||
|
|
||||||
|
4. Use Command-line arguments
|
||||||
|
* Run `py builddrivers.py -h` to get a list of options and their descriptions
|
||||||
|
* For example,
|
||||||
|
* `py builddrivers.py --PHPVER=7.0.22 --ARCH=x64 --THREAD=nts --DRIVER=sqlsrv --SOURCE`
|
||||||
|
* `py builddrivers.py --PHPVER=7.1.8 --ARCH=x86 --THREAD=ts --DEBUG`
|
||||||
|
|
||||||
|
5. Based on the given configuration, if the script detects the presence of the PHP source directory, you can choose whether to rebuild, clean or superclean:
|
||||||
|
* `rebuild` to build again using the same configuration (32 bit, thread safe, etc.)
|
||||||
|
* `clean` to remove previous builds (binaries)
|
||||||
|
* `superclean` to remove the entire `php-<version>-src` directory, which is often unnecessary
|
||||||
|
|
||||||
|
6. If you choose not to download from a GitHub repository, you will be asked to provide the full path to your local Source folder.
|
||||||
|
|
||||||
|
7. If the compilation is successful, you will be given the option to rebuild or quit.
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
If something went wrong or the build failed, the log file will be launched (you can find the log files in `C:\php-sdk`). Otherwise, the log file will not be shown, and they remain in `C:\php-sdk` until you remove them manually.
|
||||||
|
|
||||||
|
In addition to the log files in `C:\php-sdk`, you can examine the contents of `C:\php-sdk\phpsdk-build-task.bat`, which is overwritten every time you run the build scripts.
|
||||||
|
|
||||||
|
#### Testing mode and/or setting alternative destination
|
||||||
|
|
||||||
|
If your main goal is to build the drivers for testing, and/or there is no need to keep the `php-sdk` directory around, you can invoke `py builddrivers.py` with the necessary command-line arguments plus `--TESTING`, which turns on the *testing* mode (it is False by default).
|
||||||
|
|
||||||
|
Setting the testing mode automatically turns off the looping mechanism. When the build is finished, you will find a copy of the drivers (unless the build failed) and the `php-sdk` folder in the same directory of these Python scripts.
|
||||||
|
|
||||||
|
In addition, you can set an alternative destination using `--DESTPATH=<some valid path>`, which is **None** by default. Note that these two options are *not* available in the interactive mode. However, they are particularly useful for testing purposes (such as testing in a virtual machine) in which these build scripts are copied to a temporary folder. After the drivers have been successfully compiled and copied to the designated location, the temporary folder can be safely removed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
288
buildscripts/builddrivers.py
Normal file
288
buildscripts/builddrivers.py
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
#########################################################################################
|
||||||
|
#
|
||||||
|
# Description: This script helps to build drivers in a Windows environment for PHP 7+ (32-bit/64-bit)
|
||||||
|
#
|
||||||
|
# Requirement:
|
||||||
|
# python 3.x
|
||||||
|
# PHP SDK and PHP Source
|
||||||
|
# Driver source code folder / GitHub repository
|
||||||
|
# Visual Studio 2015 (PHP 7.0* and 7.1*) and Visual Studio 2017 (PHP 7.2*)
|
||||||
|
#
|
||||||
|
# Execution: Run with command line with required options.
|
||||||
|
# Examples:
|
||||||
|
# py builddrivers.py (for interactive mode)
|
||||||
|
# py builddrivers.py --PHPVER=7.0.22 --ARCH=x64 --THREAD=nts --DRIVER=all --DEBUG
|
||||||
|
#
|
||||||
|
# Output: Build the drivers using PHP SDK. When running for local development, if build is unsuccessful,
|
||||||
|
# the log file will be launched for examination. Otherwise, the drivers will be renamed
|
||||||
|
# and copied to the designated location (if defined).
|
||||||
|
#
|
||||||
|
#############################################################################################
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import os.path
|
||||||
|
import argparse
|
||||||
|
from buildtools import BuildUtil
|
||||||
|
|
||||||
|
class BuildDriver(object):
|
||||||
|
"""Build sqlsrv and/or pdo_sqlsrv drivers with PHP source with the following properties:
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
util # BuildUtil object whose constructor takes phpver, driver, arch, thread, debug
|
||||||
|
repo # GitHub repository
|
||||||
|
branch # GitHub repository branch
|
||||||
|
download_source # download source from GitHub or not
|
||||||
|
dest_path # alternative destination for the drivers (None for development builds)
|
||||||
|
rebuild # a boolean flag - whether the user is rebuilding
|
||||||
|
make_clean # a boolean flag - whether make clean is necessary
|
||||||
|
source_path # path to a local source folder
|
||||||
|
testing # whether the user has turned on testing mode
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, phpver, driver, arch, thread, debug, repo, branch, download, path, testing):
|
||||||
|
self.util = BuildUtil(phpver, driver, arch, thread, debug)
|
||||||
|
self.repo = repo
|
||||||
|
self.branch = branch
|
||||||
|
self.download_source = download
|
||||||
|
self.dest_path = path
|
||||||
|
self.testing = testing
|
||||||
|
self.rebuild = False
|
||||||
|
self.make_clean = False
|
||||||
|
self.source_path = None # None initially but will be set later if not downloading from GitHub
|
||||||
|
|
||||||
|
def show_config(self):
|
||||||
|
print()
|
||||||
|
print('PHP Version: ', self.util.phpver)
|
||||||
|
print('Arch: ', self.util.arch)
|
||||||
|
print('Thread: ', self.util.thread)
|
||||||
|
print('Driver: ', self.util.driver)
|
||||||
|
print('Debug enabled: ', self.util.debug_enabled)
|
||||||
|
print()
|
||||||
|
|
||||||
|
def clean_or_remove(self, root_dir, work_dir):
|
||||||
|
"""Only check this for local development and not rebuilding. If the php source directory
|
||||||
|
already exists, this will prompt user whether to rebuild, clean, or superclean, the last option
|
||||||
|
will remove the entire php source directory.
|
||||||
|
|
||||||
|
:param root_dir: the C:\ drive
|
||||||
|
:param work_dir: the directory of this script
|
||||||
|
:outcome: the old binaries, if exist, will be removed
|
||||||
|
"""
|
||||||
|
phpsrc = self.util.phpsrc_root(root_dir)
|
||||||
|
if os.path.exists( phpsrc ):
|
||||||
|
print(phpsrc + " exists.")
|
||||||
|
build_choice = validate_input("(r)ebuild for the same configuration, (c)lean otherwise, (s)uperclean if unsure ", "r/c/s")
|
||||||
|
self.make_clean = False
|
||||||
|
if build_choice == 'r':
|
||||||
|
print('Will rebuild the binaries')
|
||||||
|
# only the old binaries based on the current configuration will be removed
|
||||||
|
self.util.remove_prev_build(root_dir)
|
||||||
|
elif build_choice == 'c':
|
||||||
|
print('Will make clean')
|
||||||
|
self.make_clean = True
|
||||||
|
# all old builds are removed, and this step is necessary because
|
||||||
|
# the user might have changed the configuration
|
||||||
|
self.util.remove_old_builds(root_dir)
|
||||||
|
else:
|
||||||
|
print('Will remove ' + phpsrc)
|
||||||
|
os.system('RMDIR /s /q ' + phpsrc)
|
||||||
|
|
||||||
|
os.chdir(work_dir) # change back to the working directory
|
||||||
|
|
||||||
|
def build_extensions(self, root_dir, logfile):
|
||||||
|
"""This takes care of getting the drivers' source files, building the drivers.
|
||||||
|
If dest_path is defined, the binaries will be copied to the designated destinations.
|
||||||
|
|
||||||
|
:param root_dir: the root directory
|
||||||
|
:param logfile: the name of the logfile
|
||||||
|
:outcome: the drivers and symbols will renamed and placed in the appropriate location(s)
|
||||||
|
|
||||||
|
"""
|
||||||
|
work_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
if self.download_source:
|
||||||
|
# This will download from the specified branch on GitHub repo and copy the source
|
||||||
|
self.util.download_msphpsql_source(repo, branch)
|
||||||
|
else:
|
||||||
|
# This case only happens when building for development
|
||||||
|
while True:
|
||||||
|
if self.source_path is None:
|
||||||
|
source = input('Enter the full path to the Source folder: ')
|
||||||
|
else:
|
||||||
|
source = input("Hit ENTER to reuse '" + self.source_path + "' or provide another path to the Source folder: ")
|
||||||
|
if len(source) == 0:
|
||||||
|
source = self.source_path
|
||||||
|
|
||||||
|
valid = True
|
||||||
|
if os.path.exists(source) and os.path.exists(os.path.join(source, 'shared')):
|
||||||
|
# Checking the existence of 'shared' folder only, assuming
|
||||||
|
# sqlsrv and/or pdo_sqlsrv are also present if it exists
|
||||||
|
self.source_path = source
|
||||||
|
break
|
||||||
|
|
||||||
|
print("The path provided is invalid. Please re-enter.")
|
||||||
|
|
||||||
|
print('Copying source files from', source)
|
||||||
|
|
||||||
|
os.system('ROBOCOPY ' + source + '\shared ' + work_dir + '\Source\shared /xx /xo ')
|
||||||
|
os.system('ROBOCOPY ' + source + '\sqlsrv ' + work_dir + '\Source\sqlsrv /xx /xo ')
|
||||||
|
os.system('ROBOCOPY ' + source + '\pdo_sqlsrv ' + work_dir + '\Source\pdo_sqlsrv /xx /xo ')
|
||||||
|
|
||||||
|
print('Start building PHP with the extension...')
|
||||||
|
|
||||||
|
# If not testing, dest should be the root drive. Otherwise, dest should be None.
|
||||||
|
dest = None if self.testing else root_dir
|
||||||
|
|
||||||
|
# ext_dir is the directory where we can find the built extension(s)
|
||||||
|
ext_dir = self.util.build_drivers(self.make_clean, dest, logfile)
|
||||||
|
|
||||||
|
# Copy the binaries if a destination path is defined
|
||||||
|
if self.dest_path is not None:
|
||||||
|
dest_drivers = os.path.join(self.dest_path, self.util.major_version(), self.util.arch)
|
||||||
|
dest_symbols = os.path.join(dest_drivers, 'Symbols', self.util.thread)
|
||||||
|
|
||||||
|
# All intermediate directories will be created in order to create the leaf directory
|
||||||
|
if os.path.exists(dest_symbols) == False:
|
||||||
|
os.makedirs(dest_symbols)
|
||||||
|
|
||||||
|
# Now copy all the binaries
|
||||||
|
if self.util.driver == 'all':
|
||||||
|
self.util.copy_binary(ext_dir, dest_drivers, 'sqlsrv', '.dll')
|
||||||
|
self.util.copy_binary(ext_dir, dest_symbols, 'sqlsrv', '.pdb')
|
||||||
|
self.util.copy_binary(ext_dir, dest_drivers, 'pdo_sqlsrv', '.dll')
|
||||||
|
self.util.copy_binary(ext_dir, dest_symbols, 'pdo_sqlsrv', '.pdb')
|
||||||
|
else:
|
||||||
|
self.util.copy_binary(ext_dir, dest_drivers, self.util.driver, '.dll')
|
||||||
|
self.util.copy_binary(ext_dir, dest_symbols, self.util.driver, '.pdb')
|
||||||
|
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
"""This is the main entry point of building drivers for PHP.
|
||||||
|
For development, this will loop till the user decides to quit.
|
||||||
|
"""
|
||||||
|
self.show_config()
|
||||||
|
|
||||||
|
work_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
root_dir = 'C:' + os.sep
|
||||||
|
|
||||||
|
quit = False
|
||||||
|
while not quit:
|
||||||
|
if not self.rebuild and not self.testing:
|
||||||
|
self.clean_or_remove(root_dir, work_dir)
|
||||||
|
|
||||||
|
logfile = self.util.get_logfile_name()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.build_extensions(root_dir, logfile)
|
||||||
|
print('Build Completed')
|
||||||
|
except:
|
||||||
|
print('Something went wrong, launching log file', logfile)
|
||||||
|
# display log file only when not testing
|
||||||
|
if not self.testing:
|
||||||
|
os.startfile(os.path.join(root_dir, 'php-sdk', logfile))
|
||||||
|
os.chdir(work_dir)
|
||||||
|
break
|
||||||
|
|
||||||
|
if not self.testing:
|
||||||
|
choice = input("Rebuild using the same configuration(yes) or quit (no) [yes/no]: ")
|
||||||
|
choice = choice.lower()
|
||||||
|
if choice == 'yes' or choice == 'y' or choice == '':
|
||||||
|
print('Rebuilding drivers...')
|
||||||
|
self.make_clean = False
|
||||||
|
self.rebuild = True
|
||||||
|
self.util.remove_prev_build(root_dir)
|
||||||
|
else:
|
||||||
|
quit = True
|
||||||
|
else:
|
||||||
|
quit = True
|
||||||
|
|
||||||
|
os.chdir(work_dir)
|
||||||
|
|
||||||
|
def validate_input(question, values):
|
||||||
|
"""Return the user selected value, and it must be valid based on *values*."""
|
||||||
|
while True:
|
||||||
|
options = values.split('/')
|
||||||
|
prompt = '[' + values + ']'
|
||||||
|
value = input(question + prompt + ': ')
|
||||||
|
value = value.lower()
|
||||||
|
if not value in options:
|
||||||
|
print("An invalid choice is entered. Choose from", prompt)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return value
|
||||||
|
|
||||||
|
################################### Main Function ###################################
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--PHPVER', help="PHP version, e.g. 7.1.*, 7.2.* etc.")
|
||||||
|
parser.add_argument('--ARCH', choices=['x64', 'x86'])
|
||||||
|
parser.add_argument('--THREAD', choices=['nts', 'ts'])
|
||||||
|
parser.add_argument('--DRIVER', default='all', choices=['all', 'sqlsrv', 'pdo_sqlsrv'], help="driver to build (default: all)")
|
||||||
|
parser.add_argument('--DEBUG', action='store_true', help="enable debug mode (default: False)")
|
||||||
|
parser.add_argument('--REPO', default='Microsoft', help="GitHub repository (default: Microsoft)")
|
||||||
|
parser.add_argument('--BRANCH', default='dev', help="GitHub repository branch (default: dev)")
|
||||||
|
parser.add_argument('--SOURCE', action='store_true', help="get source from a local path (default: False)")
|
||||||
|
parser.add_argument('--TESTING', action='store_true', help="turns on testing mode (default: False)")
|
||||||
|
parser.add_argument('--DESTPATH', default=None, help="an alternative destination for the drivers (default: None)")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
phpver = args.PHPVER
|
||||||
|
arch = args.ARCH
|
||||||
|
thread = args.THREAD
|
||||||
|
driver = args.DRIVER
|
||||||
|
debug = args.DEBUG
|
||||||
|
repo = args.REPO
|
||||||
|
branch = args.BRANCH
|
||||||
|
download = args.SOURCE is False
|
||||||
|
path = args.DESTPATH
|
||||||
|
testing = args.TESTING
|
||||||
|
|
||||||
|
if phpver is None:
|
||||||
|
# starts interactive mode, testing mode is False
|
||||||
|
# will not prompt for drivers' destination path, which is None by default
|
||||||
|
while True:
|
||||||
|
# perform some minimal checks
|
||||||
|
phpver = input("PHP Version (e.g. 7.1.* or 7.2.*): ")
|
||||||
|
if phpver == '':
|
||||||
|
print('Empty PHP version entered! Please try again.')
|
||||||
|
elif phpver[0] < '7':
|
||||||
|
print('Only PHP 7.0 or above is supported. Please try again.')
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
arch_version = input("64-bit? [y/n]: ")
|
||||||
|
thread = validate_input("Thread safe? ", "nts/ts")
|
||||||
|
driver = validate_input("Driver to build? ", "all/sqlsrv/pdo_sqlsrv")
|
||||||
|
debug_mode = input("Debug enabled? [y/n]: ")
|
||||||
|
|
||||||
|
answer = input("Download source from a GitHub repo? [y/n]: ")
|
||||||
|
download = False
|
||||||
|
if answer == 'yes' or answer == 'y' or answer == '':
|
||||||
|
download = True
|
||||||
|
repo = input("Name of the repo (hit enter for 'Microsoft'): ")
|
||||||
|
branch = input("Name of the branch (hit enter for 'dev'): ")
|
||||||
|
if repo == '':
|
||||||
|
repo = 'Microsoft'
|
||||||
|
if branch == '':
|
||||||
|
branch = 'dev'
|
||||||
|
|
||||||
|
arch_version = arch_version.lower()
|
||||||
|
arch = 'x64' if arch_version == 'yes' or arch_version == 'y' or arch_version == '' else 'x86'
|
||||||
|
|
||||||
|
debug_mode = debug_mode.lower()
|
||||||
|
debug = debug_mode == 'yes' or debug_mode == 'y' or debug_mode == ''
|
||||||
|
|
||||||
|
builder = BuildDriver(phpver,
|
||||||
|
driver,
|
||||||
|
arch,
|
||||||
|
thread,
|
||||||
|
debug,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
download,
|
||||||
|
path,
|
||||||
|
testing)
|
||||||
|
builder.build()
|
476
buildscripts/buildtools.py
Normal file
476
buildscripts/buildtools.py
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
#########################################################################################
|
||||||
|
#
|
||||||
|
# Description: The class BuildUtil will build Microsoft SQL Server PHP 7+ Drivers
|
||||||
|
# for 32 bit and 64 bit.
|
||||||
|
#
|
||||||
|
# Requirement:
|
||||||
|
# python 3.x
|
||||||
|
# PHP SDK and PHP Source
|
||||||
|
# Driver source code folder
|
||||||
|
# Git for Windows
|
||||||
|
# Visual Studio 2015 (PHP 7.0* and 7.1*) and Visual Studio 2017 (PHP 7.2*)
|
||||||
|
#
|
||||||
|
# Output: The drivers will be renamed and copied to the specified location.
|
||||||
|
#
|
||||||
|
#############################################################################################
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import os.path
|
||||||
|
import stat
|
||||||
|
import datetime
|
||||||
|
import urllib.request
|
||||||
|
import zipfile
|
||||||
|
import fileinput
|
||||||
|
|
||||||
|
class BuildUtil(object):
|
||||||
|
"""Build sqlsrv and/or pdo_sqlsrv drivers with PHP source with the following properties:
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
phpver # PHP version, e.g. 7.1.*, 7.2.* etc.
|
||||||
|
driver # all, sqlsrv, or pdo_sqlsrv
|
||||||
|
arch # x64 or x86
|
||||||
|
thread # nts or ts
|
||||||
|
debug_enabled # whether debug is enabled
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, phpver, driver, arch, thread, debug_enabled = False):
|
||||||
|
self.phpver = phpver
|
||||||
|
self.driver = driver.lower()
|
||||||
|
self.arch = arch.lower()
|
||||||
|
self.thread = thread.lower()
|
||||||
|
self.debug_enabled = debug_enabled
|
||||||
|
|
||||||
|
def major_version(self):
|
||||||
|
"""Return the major version number based on the PHP version."""
|
||||||
|
return self.phpver[0:3]
|
||||||
|
|
||||||
|
def version_label(self):
|
||||||
|
"""Return the version label based on the PHP version."""
|
||||||
|
major_ver = self.major_version()
|
||||||
|
|
||||||
|
if major_ver[2] == '0':
|
||||||
|
version = major_ver[0]
|
||||||
|
else:
|
||||||
|
version = major_ver[0] + major_ver[2]
|
||||||
|
return version
|
||||||
|
|
||||||
|
def driver_name(self, driver, suffix):
|
||||||
|
"""Return the *driver* name with *suffix* after PHP is successfully compiled."""
|
||||||
|
return 'php_' + driver + suffix
|
||||||
|
|
||||||
|
def driver_new_name(self, driver, suffix):
|
||||||
|
"""Return the *driver* name with *suffix* based on PHP version and thread."""
|
||||||
|
version = self.version_label()
|
||||||
|
return 'php_' + driver + '_' + version + '_' + self.thread + suffix
|
||||||
|
|
||||||
|
def compiler_version(self):
|
||||||
|
"""Return the appropriate compiler version based on PHP version."""
|
||||||
|
VC = 'vc14'
|
||||||
|
version = self.version_label()
|
||||||
|
if version >= '72': # Compiler version for PHP 7.2 or above
|
||||||
|
VC = 'vc15'
|
||||||
|
return VC
|
||||||
|
|
||||||
|
def phpsrc_root(self, sdk_dir):
|
||||||
|
"""Return the path to the PHP source folder based on *sdk_dir*."""
|
||||||
|
vc = self.compiler_version()
|
||||||
|
return os.path.join(sdk_dir, 'php-sdk', 'phpdev', vc, self.arch, 'php-'+self.phpver+'-src')
|
||||||
|
|
||||||
|
def build_abs_path(self, sdk_dir):
|
||||||
|
"""Return the absolute path to the PHP build folder based on *sdk_dir*."""
|
||||||
|
phpsrc = self.phpsrc_root(sdk_dir)
|
||||||
|
|
||||||
|
build_dir = 'Release'
|
||||||
|
if self.debug_enabled:
|
||||||
|
build_dir = 'Debug'
|
||||||
|
|
||||||
|
if self.thread == 'ts':
|
||||||
|
build_dir = build_dir + '_TS'
|
||||||
|
|
||||||
|
if self.arch == 'x64':
|
||||||
|
build_dir = self.arch + os.sep + build_dir
|
||||||
|
|
||||||
|
return os.path.join(phpsrc, build_dir)
|
||||||
|
|
||||||
|
def remove_old_builds(self, sdk_dir):
|
||||||
|
"""Remove the extensions, e.g. the driver subfolders in php-7.*-src\ext."""
|
||||||
|
print('Removing old builds...')
|
||||||
|
|
||||||
|
phpsrc = self.phpsrc_root(sdk_dir)
|
||||||
|
ext_path = os.path.join(phpsrc, 'ext')
|
||||||
|
if os.path.exists( ext_path ):
|
||||||
|
shutil.rmtree(os.path.join(ext_path, 'sqlsrv'), ignore_errors=True)
|
||||||
|
shutil.rmtree(os.path.join(ext_path, 'pdo_sqlsrv'), ignore_errors=True)
|
||||||
|
|
||||||
|
if self.arch == 'x64':
|
||||||
|
shutil.rmtree(os.path.join(phpsrc, self.arch), ignore_errors=True)
|
||||||
|
else:
|
||||||
|
shutil.rmtree(os.path.join(phpsrc, 'Debug'), ignore_errors=True)
|
||||||
|
shutil.rmtree(os.path.join(phpsrc, 'Debug_TS'), ignore_errors=True)
|
||||||
|
shutil.rmtree(os.path.join(phpsrc, 'Release'), ignore_errors=True)
|
||||||
|
shutil.rmtree(os.path.join(phpsrc, 'Release_TS'), ignore_errors=True)
|
||||||
|
|
||||||
|
def remove_prev_build(self, sdk_dir):
|
||||||
|
"""Remove all binaries and source code in the Release* or Debug*
|
||||||
|
folders according to the current configuration
|
||||||
|
"""
|
||||||
|
print('Removing previous build...')
|
||||||
|
build_dir = self.build_abs_path(sdk_dir)
|
||||||
|
if not os.path.exists(build_dir):
|
||||||
|
return
|
||||||
|
|
||||||
|
os.chdir(build_dir)
|
||||||
|
os.system('DEL *sqlsrv*')
|
||||||
|
|
||||||
|
# remove the extensions in the phpsrc's release* or debug* folder's ext subfolder
|
||||||
|
release_ext_path = os.path.join(build_dir, 'ext')
|
||||||
|
if os.path.exists( release_ext_path ):
|
||||||
|
shutil.rmtree(os.path.join(release_ext_path, 'sqlsrv'), ignore_errors=True)
|
||||||
|
shutil.rmtree(os.path.join(release_ext_path, 'pdo_sqlsrv'), ignore_errors=True)
|
||||||
|
|
||||||
|
# next remove the binaries too
|
||||||
|
os.chdir(release_ext_path)
|
||||||
|
os.system('DEL *sqlsrv*')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_logfile_name():
|
||||||
|
"""Return the filename for the log file based on timestamp."""
|
||||||
|
return 'Build_' + datetime.datetime.now().strftime("%Y%m%d_%H%M") + '.log'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_file_content(file, search_str, new_str):
|
||||||
|
"""Find *search_str* and replace it by *new_str* in a *file*"""
|
||||||
|
os.chmod(file, stat.S_IWRITE)
|
||||||
|
with fileinput.FileInput(file, inplace=True) as f:
|
||||||
|
for line in f:
|
||||||
|
print(line.replace(search_str, new_str), end='')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generateMMDD():
|
||||||
|
"""Return the generated Microsoft PHP Build Version Number"""
|
||||||
|
d = datetime.date.today()
|
||||||
|
|
||||||
|
startYear = 2009
|
||||||
|
startMonth = 4
|
||||||
|
passYear = int( '%02d' % d.year ) - startYear
|
||||||
|
passMonth = int( '%02d' % d.month ) - startMonth
|
||||||
|
MM = passYear * 12 + passMonth
|
||||||
|
dd = d.day
|
||||||
|
|
||||||
|
MMDD = "" + str( MM )
|
||||||
|
if( dd < 10 ):
|
||||||
|
return MMDD + "0" + str( dd )
|
||||||
|
else:
|
||||||
|
return MMDD + str( dd )
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_driver_version(version_file):
|
||||||
|
"""Read the *version_file* and return the driver version."""
|
||||||
|
with open(version_file) as f:
|
||||||
|
for line in f:
|
||||||
|
if 'SQLVERSION_MAJOR' in line: # major version
|
||||||
|
major = line.split()[2]
|
||||||
|
elif 'SQLVERSION_MINOR' in line: # minor version
|
||||||
|
minor = line.split()[2]
|
||||||
|
elif 'SQLVERSION_PATCH' in line: # patch
|
||||||
|
patch = line.split()[2]
|
||||||
|
break
|
||||||
|
|
||||||
|
return major + '.' + minor + '.' + patch
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def write_lines_to_copy_source(driver, file):
|
||||||
|
"""Write to file the commands to copy *driver* source."""
|
||||||
|
source = '%currDir%' + os.sep + 'Source' + os.sep + driver
|
||||||
|
dest = '%phpSrc%' + os.sep + 'ext' + os.sep + driver
|
||||||
|
file.write('@CALL ROBOCOPY ' + source + ' ' + dest + ' /s /xx /xo' + os.linesep)
|
||||||
|
|
||||||
|
source = '%currDir%' + os.sep + 'Source' + os.sep + 'shared'
|
||||||
|
dest = '%phpSrc%' + os.sep + 'ext' + os.sep + driver + os.sep + 'shared'
|
||||||
|
file.write('@CALL ROBOCOPY ' + source + ' ' + dest + ' /s /xx /xo' + os.linesep)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def download_msphpsql_source(repo, branch, dest_folder = 'Source', clean_up = True):
|
||||||
|
"""Download to *dest_folder* the msphpsql archive of the specified
|
||||||
|
GitHub *repo* and *branch*. The downloaded files will be removed by default.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
work_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
temppath = os.path.join(work_dir, 'temp')
|
||||||
|
if os.path.exists(temppath):
|
||||||
|
shutil.rmtree(temppath)
|
||||||
|
os.makedirs(temppath)
|
||||||
|
os.chdir(temppath)
|
||||||
|
|
||||||
|
file = branch + '.zip'
|
||||||
|
url = 'https://github.com/' + repo + '/msphpsql/archive/' + branch + '.zip'
|
||||||
|
|
||||||
|
print('Downloading ' + url + ' ...')
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(url) as response, open(file, 'wb') as out_file:
|
||||||
|
shutil.copyfileobj(response, out_file)
|
||||||
|
except:
|
||||||
|
print ("Resort to skip ssl verification...")
|
||||||
|
# need to skip ssl verification on some agents
|
||||||
|
# see https://www.python.org/dev/peps/pep-0476/
|
||||||
|
with urllib.request.urlopen(url, context=ssl._create_unverified_context()) as response, open(file, 'wb') as out_file:
|
||||||
|
shutil.copyfileobj(response, out_file)
|
||||||
|
|
||||||
|
print('Extracting ' + file + ' ...')
|
||||||
|
zip = zipfile.ZipFile(file)
|
||||||
|
zip.extractall()
|
||||||
|
zip.close()
|
||||||
|
|
||||||
|
msphpsqlFolder = os.path.join(temppath, 'msphpsql-' + branch)
|
||||||
|
source = os.path.join(msphpsqlFolder, 'source')
|
||||||
|
os.chdir(work_dir)
|
||||||
|
|
||||||
|
os.system('ROBOCOPY ' + source + '\shared ' + dest_folder + '\shared /xx /xo')
|
||||||
|
os.system('ROBOCOPY ' + source + '\pdo_sqlsrv ' + dest_folder + '\pdo_sqlsrv /xx /xo')
|
||||||
|
os.system('ROBOCOPY ' + source + '\sqlsrv ' + dest_folder + '\sqlsrv /xx /xo')
|
||||||
|
|
||||||
|
if clean_up:
|
||||||
|
shutil.rmtree(temppath)
|
||||||
|
|
||||||
|
except:
|
||||||
|
print('Error occurred when downloading source')
|
||||||
|
raise
|
||||||
|
|
||||||
|
def update_driver_source(self, source_dir, driver):
|
||||||
|
"""Update the *driver* source in *source_path* with the
|
||||||
|
latest version, file descriptions, etc.
|
||||||
|
If debug is enabled, will remove the optimization flag
|
||||||
|
"""
|
||||||
|
driver_dir = os.path.join(source_dir, driver)
|
||||||
|
|
||||||
|
if self.debug_enabled:
|
||||||
|
# Remove the optimization flag in the config file for this driver
|
||||||
|
# because '/O2' option is incompatible with Debug mode
|
||||||
|
print('Removing optimization flag for', driver)
|
||||||
|
config_file = os.path.join(driver_dir, 'config.w32')
|
||||||
|
if driver == 'sqlsrv':
|
||||||
|
self.update_file_content(config_file, 'ADD_FLAG( "CFLAGS_SQLSRV", "/O2" );', '')
|
||||||
|
elif driver == 'pdo_sqlsrv':
|
||||||
|
self.update_file_content(config_file, 'ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/O2" );', '')
|
||||||
|
|
||||||
|
# Update Template.rc
|
||||||
|
template_file = os.path.join(driver_dir, 'template.rc')
|
||||||
|
if driver == 'sqlsrv':
|
||||||
|
drivername = self.driver_new_name(driver, '.dll')
|
||||||
|
self.update_file_content(template_file, 'FILE_NAME \"\\0\"', '"' + drivername + '\\0"')
|
||||||
|
self.update_file_content(template_file, '\"Microsoft Drivers for PHP for SQL Server\\0\"', '"Microsoft Drivers for PHP for SQL Server (SQLSRV Driver)\\0"')
|
||||||
|
elif driver == 'pdo_sqlsrv':
|
||||||
|
drivername = self.driver_new_name(driver, '.dll')
|
||||||
|
self.update_file_content(template_file, 'FILE_NAME \"\\0\"', '"' + drivername + '\\0"')
|
||||||
|
self.update_file_content(template_file, '\"Microsoft Drivers for PHP for SQL Server\\0\"', '"Microsoft Drivers for PHP for SQL Server (PDO Driver)\\0"')
|
||||||
|
|
||||||
|
# Update Version.h
|
||||||
|
version_file = os.path.join(source_dir, 'shared', 'version.h')
|
||||||
|
build_number = self.generateMMDD()
|
||||||
|
self.update_file_content(version_file, 'SQLVERSION_BUILD 0', 'SQLVERSION_BUILD ' + build_number)
|
||||||
|
|
||||||
|
# get the latest version
|
||||||
|
version = self.get_driver_version(version_file) + '.' + build_number
|
||||||
|
print('Driver version is: ', version)
|
||||||
|
|
||||||
|
# Update CREDIT file
|
||||||
|
credits_file = os.path.join(driver_dir, 'CREDITS')
|
||||||
|
if driver == 'sqlsrv':
|
||||||
|
self.update_file_content(credits_file, 'Microsoft Drivers for PHP for SQL Server', 'Microsoft Drivers ' + version + ' for PHP for SQL Server (' + self.driver.upper() + ' driver)')
|
||||||
|
elif driver == 'pdo_sqlsrv':
|
||||||
|
self.update_file_content(credits_file, 'Microsoft Drivers for PHP for SQL Server (PDO driver)', 'Microsoft Drivers ' + version + ' for PHP for SQL Server (' + self.driver.upper() + ' driver)')
|
||||||
|
|
||||||
|
def generate_build_options(self):
|
||||||
|
"""Return the generated build configuration and arguments"""
|
||||||
|
cmd_line = ''
|
||||||
|
if self.debug_enabled:
|
||||||
|
cmd_line = ' --enable-debug '
|
||||||
|
|
||||||
|
if self.driver == 'all':
|
||||||
|
cmd_line = ' --enable-sqlsrv=shared --enable-pdo --with-pdo-sqlsrv=shared ' + cmd_line
|
||||||
|
else:
|
||||||
|
if self.driver == 'sqlsrv':
|
||||||
|
cmd_line = ' --enable-sqlsrv=shared ' + cmd_line
|
||||||
|
else: # pdo_sqlsrv
|
||||||
|
cmd_line = ' --enable-pdo --with-pdo-sqlsrv=shared ' + cmd_line
|
||||||
|
|
||||||
|
cmd_line = 'cscript configure.js --disable-all --enable-cli --enable-cgi --enable-embed' + cmd_line
|
||||||
|
if self.thread == 'nts':
|
||||||
|
cmd_line = cmd_line + ' --disable-zts'
|
||||||
|
return cmd_line
|
||||||
|
|
||||||
|
def create_local_batch_file(self, make_clean, cmd_line, log_file):
|
||||||
|
"""Generate the batch file to be picked up by the PHP starter script."""
|
||||||
|
filename = 'phpsdk-build-task.bat'
|
||||||
|
print('Generating ', filename)
|
||||||
|
try:
|
||||||
|
file = open(filename, 'w')
|
||||||
|
file.write('@ECHO OFF' + os.linesep)
|
||||||
|
file.write('SET currDir=%CD%' + os.linesep)
|
||||||
|
file.write('SET LOG_NAME=%currDir%\\' + log_file + os.linesep)
|
||||||
|
file.write('@CALL phpsdk_buildtree phpdev > %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
|
||||||
|
# for PHP version with release tags, such as 'RC', 'beta', etc.
|
||||||
|
# we need to remove the hyphen '-' between the version number and tag
|
||||||
|
# because in https://github.com/php/php-src the released tags have no hyphens
|
||||||
|
|
||||||
|
php_tag = 'php-' + self.phpver.replace('-', '')
|
||||||
|
php_src = 'php-' + self.phpver +'-src'
|
||||||
|
|
||||||
|
# if not exists, check out the specified tag
|
||||||
|
file.write('IF NOT EXIST ' + php_src + ' @CALL git clone -b ' + php_tag + ' --depth 1 --single-branch https://github.com/php/php-src.git ' + php_src + os.linesep)
|
||||||
|
file.write('CD ' + php_src + os.linesep)
|
||||||
|
file.write('SET phpSrc=%CD%' + os.linesep)
|
||||||
|
file.write('@CALL phpsdk_deps -u >> %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
|
||||||
|
# copy source files to extension
|
||||||
|
if self.driver == 'all':
|
||||||
|
self.write_lines_to_copy_source('sqlsrv', file)
|
||||||
|
self.write_lines_to_copy_source('pdo_sqlsrv', file)
|
||||||
|
else:
|
||||||
|
self.write_lines_to_copy_source(self.driver, file)
|
||||||
|
|
||||||
|
# configure and build
|
||||||
|
file.write('@CALL buildconf --force >> %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
file.write('@CALL ' + cmd_line + ' >> %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
if make_clean:
|
||||||
|
file.write('nmake clean >> %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
file.write('nmake >> %LOG_NAME% 2>&1' + os.linesep)
|
||||||
|
file.write('exit' + os.linesep)
|
||||||
|
file.close()
|
||||||
|
return filename
|
||||||
|
except:
|
||||||
|
print('Cannot create ', filename)
|
||||||
|
|
||||||
|
def build_drivers(self, make_clean = False, dest = None, log_file = None):
|
||||||
|
"""Build sqlsrv/pdo_sqlsrv extensions for PHP, assuming the Source folder
|
||||||
|
exists in the working directory, and this folder will be removed when the build
|
||||||
|
is complete.
|
||||||
|
"""
|
||||||
|
work_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
# First, update the driver source file contents
|
||||||
|
source_dir = os.path.join(work_dir, 'Source')
|
||||||
|
if self.driver == 'all':
|
||||||
|
self.update_driver_source(source_dir, 'sqlsrv')
|
||||||
|
self.update_driver_source(source_dir, 'pdo_sqlsrv')
|
||||||
|
else:
|
||||||
|
self.update_driver_source(source_dir, self.driver)
|
||||||
|
|
||||||
|
# Next, generate the build configuration and arguments
|
||||||
|
cmd_line = self.generate_build_options()
|
||||||
|
print('cmd_line: ' + cmd_line)
|
||||||
|
|
||||||
|
# Generate a batch file based on the inputs
|
||||||
|
if log_file is None:
|
||||||
|
log_file = self.get_logfile_name()
|
||||||
|
|
||||||
|
batch_file = self.create_local_batch_file(make_clean, cmd_line, log_file)
|
||||||
|
|
||||||
|
# Reference: https://github.com/OSTC/php-sdk-binary-tools
|
||||||
|
# Clone the master branch of PHP sdk if the directory does not exist
|
||||||
|
print('Downloading the latest php SDK...')
|
||||||
|
|
||||||
|
# if *dest* is None, simply use the current working directory
|
||||||
|
sdk_dir = dest
|
||||||
|
copy_to_ext = True # this determines where to copy the binaries to
|
||||||
|
if dest is None:
|
||||||
|
sdk_dir = work_dir
|
||||||
|
copy_to_ext = False
|
||||||
|
|
||||||
|
phpSDK = os.path.join(sdk_dir, 'php-sdk')
|
||||||
|
if not os.path.exists( phpSDK ):
|
||||||
|
os.system('git clone https://github.com/OSTC/php-sdk-binary-tools.git --branch master --single-branch --depth 1 ' + phpSDK)
|
||||||
|
os.chdir(phpSDK)
|
||||||
|
os.system('git pull ')
|
||||||
|
|
||||||
|
# Move the generated batch file to phpSDK for the php starter script
|
||||||
|
sdk_batch_file = os.path.join(phpSDK, batch_file)
|
||||||
|
if os.path.exists(sdk_batch_file):
|
||||||
|
os.remove(sdk_batch_file)
|
||||||
|
shutil.move(os.path.join(work_dir, batch_file), phpSDK)
|
||||||
|
|
||||||
|
sdk_source = os.path.join(phpSDK, 'Source')
|
||||||
|
# Sometimes, for various reasons, the Source folder from previous build
|
||||||
|
# might exist in phpSDK. If so, remove it first
|
||||||
|
if os.path.exists(sdk_source):
|
||||||
|
os.chmod(sdk_source, stat.S_IWRITE)
|
||||||
|
shutil.rmtree(sdk_source, ignore_errors=True)
|
||||||
|
shutil.move(source_dir, phpSDK)
|
||||||
|
|
||||||
|
# Invoke phpsdk-<vc>-<arch>.bat
|
||||||
|
vc = self.compiler_version()
|
||||||
|
starter_script = 'phpsdk-' + vc + '-' + self.arch + '.bat'
|
||||||
|
print('Running starter script: ', starter_script)
|
||||||
|
os.system(starter_script + ' -t ' + batch_file)
|
||||||
|
|
||||||
|
# Now we can safely remove the Source folder, because its contents have
|
||||||
|
# already been modified prior to building the extensions
|
||||||
|
shutil.rmtree(os.path.join(phpSDK, 'Source'), ignore_errors=True)
|
||||||
|
|
||||||
|
# Next, rename the newly compiled PHP extensions
|
||||||
|
self.rename_binaries(sdk_dir)
|
||||||
|
|
||||||
|
# Final step, copy the binaries to the right place
|
||||||
|
ext_dir = self.copy_binaries(sdk_dir, copy_to_ext)
|
||||||
|
return ext_dir
|
||||||
|
|
||||||
|
def rename_binary(self, path, driver):
|
||||||
|
"""Rename the *driver* binary (sqlsrv or pdo_sqlsrv) (only the dlls)."""
|
||||||
|
driver_old_name = self.driver_name(driver, '.dll')
|
||||||
|
driver_new_name = self.driver_new_name(driver, '.dll')
|
||||||
|
|
||||||
|
os.rename(os.path.join(path, driver_old_name), os.path.join(path, driver_new_name))
|
||||||
|
|
||||||
|
def rename_binaries(self, sdk_dir):
|
||||||
|
"""Rename the sqlsrv and/or pdo_sqlsrv dlls according to the PHP
|
||||||
|
version and thread.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Derive the path to where the extensions are located
|
||||||
|
ext_dir = self.build_abs_path(sdk_dir)
|
||||||
|
print("Renaming binaries in ", ext_dir)
|
||||||
|
|
||||||
|
if self.driver == 'all':
|
||||||
|
self.rename_binary(ext_dir, 'sqlsrv')
|
||||||
|
self.rename_binary(ext_dir, 'pdo_sqlsrv')
|
||||||
|
else:
|
||||||
|
self.rename_binary(ext_dir, self.driver)
|
||||||
|
|
||||||
|
def copy_binary(self, from_dir, dest_dir, driver, suffix):
|
||||||
|
"""Copy sqlsrv or pdo_sqlsrv binary (based on *suffix*) to *dest_dir*."""
|
||||||
|
if suffix == '.dll':
|
||||||
|
binary = self.driver_new_name(driver, suffix)
|
||||||
|
else:
|
||||||
|
binary = self.driver_name(driver, suffix)
|
||||||
|
shutil.copy2(os.path.join(from_dir, binary), dest_dir)
|
||||||
|
|
||||||
|
def copy_binaries(self, sdk_dir, copy_to_ext):
|
||||||
|
"""Copy the sqlsrv and/or pdo_sqlsrv binaries, including the pdb files,
|
||||||
|
to the right place, depending on *copy_to_ext*. The default is to
|
||||||
|
copy them to the 'ext' folder.
|
||||||
|
"""
|
||||||
|
build_dir = self.build_abs_path(sdk_dir)
|
||||||
|
print('Copying the binaries from', build_dir)
|
||||||
|
if copy_to_ext:
|
||||||
|
dest_dir = os.path.join(build_dir, 'ext')
|
||||||
|
else:
|
||||||
|
# Simply make a copy of the binaries in sdk_dir
|
||||||
|
dest_dir = sdk_dir
|
||||||
|
|
||||||
|
print('Destination:', dest_dir)
|
||||||
|
|
||||||
|
# Now copy the binaries
|
||||||
|
if self.driver == 'all':
|
||||||
|
self.copy_binary(build_dir, dest_dir, 'sqlsrv', '.dll')
|
||||||
|
self.copy_binary(build_dir, dest_dir, 'sqlsrv', '.pdb')
|
||||||
|
self.copy_binary(build_dir, dest_dir, 'pdo_sqlsrv', '.dll')
|
||||||
|
self.copy_binary(build_dir, dest_dir, 'pdo_sqlsrv', '.pdb')
|
||||||
|
else:
|
||||||
|
self.copy_binary(build_dir, dest_dir, self.driver, '.dll')
|
||||||
|
self.copy_binary(build_dir, dest_dir, self.driver, '.pdb')
|
||||||
|
|
||||||
|
return dest_dir
|
||||||
|
|
Loading…
Reference in a new issue