/ build_msvc / msvc-autogen.py
msvc-autogen.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2016-2022 The Bitcoin Core developers
  3  # Distributed under the MIT software license, see the accompanying
  4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5  
  6  import os
  7  import re
  8  import argparse
  9  from shutil import copyfile
 10  
 11  SOURCE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src'))
 12  DEFAULT_PLATFORM_TOOLSET = R'v143'
 13  
 14  libs = [
 15      'libbitcoin_cli',
 16      'libbitcoin_common',
 17      'libbitcoin_crypto',
 18      'libbitcoin_node',
 19      'libbitcoin_util',
 20      'libbitcoin_wallet_tool',
 21      'libbitcoin_wallet',
 22      'libbitcoin_zmq',
 23      'bench_bitcoin',
 24      'libtest_util',
 25  ]
 26  
 27  ignore_list = [
 28  ]
 29  
 30  lib_sources = {}
 31  
 32  
 33  def parse_makefile(makefile):
 34      with open(makefile, 'r', encoding='utf-8') as file:
 35          current_lib = ''
 36          for line in file.read().splitlines():
 37              if current_lib:
 38                  source = line.split()[0]
 39                  if source.endswith('.cpp') and not source.startswith('$') and source not in ignore_list:
 40                      source_filename = source.replace('/', '\\')
 41                      object_filename = source.replace('/', '_')[:-4] + ".obj"
 42                      lib_sources[current_lib].append((source_filename, object_filename))
 43                  if not line.endswith('\\'):
 44                      current_lib = ''
 45                  continue
 46              for lib in libs:
 47                  _lib = lib.replace('-', '_')
 48                  if re.search(_lib + '.*_SOURCES \\= \\\\', line):
 49                      current_lib = lib
 50                      lib_sources[current_lib] = []
 51                      break
 52  
 53  def parse_config_into_btc_config():
 54      def find_between( s, first, last ):
 55          try:
 56              start = s.index( first ) + len( first )
 57              end = s.index( last, start )
 58              return s[start:end]
 59          except ValueError:
 60              return ""
 61  
 62      config_info = []
 63      with open(os.path.join(SOURCE_DIR,'../configure.ac'), encoding="utf8") as f:
 64          for line in f:
 65              if line.startswith("define"):
 66                  config_info.append(find_between(line, "(_", ")"))
 67  
 68      config_info = [c for c in config_info if not c.startswith("COPYRIGHT_HOLDERS")]
 69  
 70      config_dict = dict(item.split(", ") for item in config_info)
 71      config_dict["PACKAGE_VERSION"] = f"\"{config_dict['CLIENT_VERSION_MAJOR']}.{config_dict['CLIENT_VERSION_MINOR']}.{config_dict['CLIENT_VERSION_BUILD']}\""
 72      version = config_dict["PACKAGE_VERSION"].strip('"')
 73      config_dict["PACKAGE_STRING"] = f"\"Bitcoin Core {version}\""
 74  
 75      with open(os.path.join(SOURCE_DIR,'../build_msvc/bitcoin_config.h.in'), "r", encoding="utf8") as template_file:
 76          template = template_file.readlines()
 77  
 78      for index, line in enumerate(template):
 79          header = ""
 80          if line.startswith("#define"):
 81              header = line.split(" ")[1]
 82          if header in config_dict:
 83              template[index] = line.replace("$", f"{config_dict[header]}")
 84  
 85      with open(os.path.join(SOURCE_DIR,'../build_msvc/bitcoin_config.h'), "w", encoding="utf8") as btc_config:
 86          btc_config.writelines(template)
 87  
 88  def set_properties(vcxproj_filename, placeholder, content):
 89      with open(vcxproj_filename + '.in', 'r', encoding='utf-8') as vcxproj_in_file:
 90          with open(vcxproj_filename, 'w', encoding='utf-8') as vcxproj_file:
 91              vcxproj_file.write(vcxproj_in_file.read().replace(placeholder, content))
 92  
 93  def main():
 94      parser = argparse.ArgumentParser(description='Bitcoin-core msbuild configuration initialiser.')
 95      parser.add_argument('-toolset', nargs='?', default=DEFAULT_PLATFORM_TOOLSET,
 96          help='Optionally sets the msbuild platform toolset, e.g. v143 for Visual Studio 2022.'
 97           ' default is %s.'%DEFAULT_PLATFORM_TOOLSET)
 98      args = parser.parse_args()
 99      set_properties(os.path.join(SOURCE_DIR, '../build_msvc/common.init.vcxproj'), '@TOOLSET@', args.toolset)
100  
101      for makefile_name in os.listdir(SOURCE_DIR):
102          if 'Makefile' in makefile_name:
103              parse_makefile(os.path.join(SOURCE_DIR, makefile_name))
104      for key, value in lib_sources.items():
105          vcxproj_filename = os.path.abspath(os.path.join(os.path.dirname(__file__), key, key + '.vcxproj'))
106          content = ''
107          for source_filename, object_filename in value:
108              content += '    <ClCompile Include="..\\..\\src\\' + source_filename + '">\n'
109              content += '      <ObjectFileName>$(IntDir)' + object_filename + '</ObjectFileName>\n'
110              content += '    </ClCompile>\n'
111          set_properties(vcxproj_filename, '@SOURCE_FILES@\n', content)
112      parse_config_into_btc_config()
113      copyfile(os.path.join(SOURCE_DIR,'../build_msvc/bitcoin_config.h'), os.path.join(SOURCE_DIR, 'config/bitcoin-config.h'))
114  
115  if __name__ == '__main__':
116      main()