diff --git a/README.md b/README.md index 0d158bf..bd532cf 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - [CMAKE 3.12.18081601-MSVC_2](https://cmake.org/) - [SWIG 4.0.2](http://www.swig.org/) - [NuGet 5.3.1](https://nuget.org) - - Ubuntu 18.4 on WSL2 + - Ubuntu 20.04.1 LTS on WSL2 - Visual Studio 2019 ## How to Build @@ -25,10 +25,10 @@ ### Preparation - Use Windows 10 (x64). -- Install Ubuntu 18.4 on WSL2 and install dotnet, boost, cairo, cmake, and swig. +- Install Ubuntu 18.4 on WSL2 and install `dotnet`, `boost`, `cairo`, `cmake`, and `swig`. - Install Visual Studio 2019 enabling C++, C# and CMAKE. - Install Python. -- Clone this repository to some directory. A name of the directory including path should be short. It is highly recommended to place it under 'C:\' folder. +- Clone this repository to some directory. A name of the directory including path should be short. It is highly recommended to place it under 'C:\'. - Download the following source archives and extract them here. - [RDKit](hhttps://github.com/rdkit/rdkit/) to `rdkit-Release_####_##_#`. - [Eigen3](http://eigen.tuxfamily.org/) to `eigen-#.#.#`. @@ -63,7 +63,7 @@ - Execute `python .\build_rdkit_csharp.py --build_libpng --build_platform all` to make libpng. - Execute `python .\build_rdkit_csharp.py --build_pixman --build_platform all` to make pixman. - Execute `python .\build_rdkit_csharp.py --build_cairo --build_platform all` to make cairo. -- Execute `python .\build_rdkit_csharp.py --build_rdkit --build_platform all` to patch RDKit and make it. -- Execute `python .\build_rdkit_csharp.py --build_wrapper` to make rdkit .NET wrapper and patch it. -- C# project file is created in `rdkit-Release_####_##_#/Code/JavaWrappers/csharp_wrapper/RDKit2DotNet.csproj`. -- Execute `python .\build_rdkit_csharp.py --build_nuget` to make NuGet package. +- Execute `python .\build_rdkit_csharp.py --build_rdkit --build_platform all` to make RDKit for Windows. +- Execute `wsl bash build_rdkit.sh` to make RDKit for Linux. +- Execute `python .\build_rdkit_csharp.py --build_wrapper` to make RDKit .NET wrapper. +- Execute `python .\build_rdkit_csharp.py --build_nuget` to make NuGet package, which includes both Windows and Linux versions. diff --git a/build_all.bat b/build_all.bat index 493da44..7dc9d19 100644 --- a/build_all.bat +++ b/build_all.bat @@ -9,7 +9,7 @@ python .\build_rdkit_csharp.py --build_freetype --build_zlib --build_libpng --bu wsl bash build_rdkit.sh @if errorlevel 1 goto :ERROREND -python .\build_rdkit_csharp.py --build_wrapper --build_nuget --build_platform all +python .\build_rdkit_csharp.py --build_wrapper --build_nuget @if errorlevel 1 goto :ERROREND @goto :END @@ -19,7 +19,7 @@ python .\build_rdkit_csharp.py --build_wrapper --build_nuget --build_platform a exit /b 1 :CL_NOT_FOUND -@echo cl is not found. Execute 'Developer Command Prompt for VS 2017' first. +@echo cl is not found. Execute 'Developer Command Prompt for VS 2019' first. exit /b 1 :END diff --git a/build_rdkit_csharp.py b/build_rdkit_csharp.py index d2c1203..d3a335a 100644 --- a/build_rdkit_csharp.py +++ b/build_rdkit_csharp.py @@ -19,6 +19,7 @@ from pathlib import Path from typing import ( Any, + Collection, Dict, Iterable, List, @@ -356,6 +357,198 @@ def get_version_for_pixman(self) -> str: def get_version_for_cairo(self) -> str: return re.sub(r".*(\d+\.\d+\.\d+)", r"\1", str(self.cairo_path)) + def run_msbuild(self, proj: Union[PathLike, str], platform: Optional[str] = None) -> None: + if not platform: + platform = self.ms_build_platform + cmd = [ + "MSBuild", + str(proj), + f"/p:Configuration=Release,Platform={platform}", + "/maxcpucount", + ] + call_subprocess(cmd) + + def make_zlib(self) -> None: + build_path = self.zlib_path / self.build_dir_name + build_path.mkdir(exist_ok=True) + _curdir = os.path.abspath(os.curdir) + try: + os.chdir(build_path) + cmd = ["cmake", str(self.zlib_path)] + list(self.g_option_of_cmake) + call_subprocess(cmd) + self.run_msbuild("zlib.sln") + shutil.copy2(build_path / "zconf.h", self.zlib_path) + finally: + os.chdir(_curdir) + + def make_libpng(self) -> None: + build_path = self.libpng_path / self.build_dir_name + build_path.mkdir(exist_ok=True) + _curdir = os.path.abspath(os.curdir) + try: + os.chdir(build_path) + cmd = ( + ["cmake", str(self.libpng_path)] + + list(self.g_option_of_cmake) + + [ + f'-DZLIB_LIBRARY="{self.zlib_path / self.build_dir_name / "Release" / "zlib.lib"}"', + f'-DZLIB_INCLUDE_DIR="{str(self.zlib_path)}"', + "-DPNG_SHARED=ON", + "-DPNG_STATIC=OFF", + ] + ) + call_subprocess(cmd) + self.run_msbuild("libpng.sln") + finally: + os.chdir(_curdir) + + def vs15_proj_to_vs16(self, proj_file: Path) -> None: + _V = "VCProjectVersion" + _P = "PlatformToolset" + replace_file_string( + proj_file, + [ + (f"\\<{_V}>15\\.0\\<\\/{_V}\\>", f"<{_V}>{get_vs_ver()}",), + ( + f"\\<{_P}\\>v141\\<\\/{_P}\\>", + f"<{_P}>v{get_msvc_internal_ver().replace('.', '')}", + ), + ], + ) + + def make_pixman(self) -> None: + _curdir = os.path.abspath(os.curdir) + try: + proj_dir = self.pixman_path / "vc2017" + proj_dir.mkdir(exist_ok=True) + os.chdir(proj_dir) + files_dir = self.this_path / "files" / "pixman" + vcxproj = "pixman.vcxproj" + shutil.copy2(files_dir / vcxproj, proj_dir) + proj_file = proj_dir / vcxproj + shutil.copy2(files_dir / "config.h", self.pixman_path / "pixman") + + self.vs15_proj_to_vs16(proj_file) + + makefile_win32 = self.pixman_path / "pixman" / "Makefile.win32" + makefile_sources = self.pixman_path / "pixman" / "Makefile.sources" + + c_files: List[str] = [] + i_files: List[str] = [] + + pattern_c = re.compile("^libpixman_sources\\s*\\=(?P.*)$") + pattern_h = re.compile("^libpixman_headers\\s*\\=(?P.*)$") + for line in makefile_to_lines(makefile_sources): + match_and_add(pattern_c, c_files, line) + match_and_add(pattern_h, i_files, line) + + pattern_c = re.compile("^\\s*libpixman_sources\\s*\\+\\=(?P.*)$") + for line in makefile_to_lines(makefile_win32): + match_and_add(pattern_c, c_files, line) + + tree = load_msbuild_xml(proj_file) + root = tree.getroot() + item_group = SubElement(root, "ItemGroup") + for name in c_files: + node = SubElement(item_group, "ClCompile") + node.attrib["Include"] = f"..\\pixman\\{name}" + for name in i_files: + node = SubElement(item_group, "ClInclude") + node.attrib["Include"] = f"..\\pixman\\{name}" + + tree.write(proj_file, "utf-8", True) + self.run_msbuild(proj_file) + finally: + os.chdir(_curdir) + + def make_cairo(self) -> None: + # TODO: get file names from src\Makefile.sources + _curdir = os.path.abspath(os.curdir) + try: + proj_dir = self.cairo_path / "vc2017" + proj_dir.mkdir(exist_ok=True) + os.chdir(proj_dir) + files_dir = self.this_path / "files" / "cairo" + vcxproj = "cairo.vcxproj" + shutil.copy2(files_dir / vcxproj, proj_dir) + proj_file = proj_dir / vcxproj + shutil.copy2(files_dir / "cairo-features.h", self.cairo_path / "src") + self.vs15_proj_to_vs16(proj_file) + replace_file_string( + proj_file, + [ + ("__CAIRODIR__", str(self.cairo_path).replace("\\", "\\\\"),), + ("__LIBPNGDIR__", str(self.libpng_path).replace("\\", "\\\\"),), + ("__ZLIBDIR__", str(self.zlib_path).replace("\\", "\\\\"),), + ("__PIXMANDIR__", str(self.pixman_path).replace("\\", "\\\\"),), + ("__FREETYPEDIR__", str(self.freetype_path).replace("\\", "\\\\"),), + ], + ) + self.run_msbuild(vcxproj) + finally: + os.chdir(_curdir) + + def make_freetype(self) -> None: + _curdir = os.path.abspath(os.curdir) + try: + os.chdir(self.freetype_path) + shutil.copy2( + self.this_path / "files" / "freetype" / "freetype.vcxproj", + self.freetype_path / "builds" / "windows" / "vc2010", + ) + os.chdir(self.freetype_path / "builds" / "windows" / "vc2010") + logging.debug(f"current dir = {os.getcwd()}") + self.run_msbuild("freetype.sln") + finally: + os.chdir(_curdir) + + @property + def path_GraphMolCSharp_i(self): + return self.rdkit_csharp_wrapper_path / "GraphMolCSharp.i" + + @property + def path_MolDraw2D_i(self): + return self.rdkit_path / "Code" / "JavaWrappers" / "MolDraw2D.i" + + @property + def path_RDKit2DotNet_folder(self): + return self.rdkit_csharp_wrapper_path / "RDKit2DotNet" + + def build_rdkit(self) -> None: + self.rdkit_csharp_build_path.mkdir(exist_ok=True) + _curdir = os.path.abspath(os.curdir) + os.chdir(self.rdkit_csharp_build_path) + try: + self._patch_i_files() + self._make_rdkit_cmake() + self._build_rdkit_native() + self._copy_dlls() + finally: + os.chdir(_curdir) + + def _patch_i_files(self): + if self.config.swig_patch_enabled: + replace_file_string( + self.path_GraphMolCSharp_i, + [("boost::int32_t", "int32_t",), ("boost::uint32_t", "uint32_t",),], + make_backup=True, + ) + if self.config.cairo_support: + insert_line_after( + self.path_MolDraw2D_i, + { + r"#include ": r"#include ", # NOQA + r"%include ": r"%include ", # NOQA + }, + make_backup=True, + ) + + def _make_rdkit_cmake(self) -> None: + cmd: List[str] = self._get_cmake_rdkit_cmd_line() + if get_os() == "win": + cmd = [a.replace("\\", "/") for a in cmd] + call_subprocess(cmd) + def _get_cmake_rdkit_cmd_line(self) -> List[str]: def f_test(): return "ON" if self.config.test_enabled else "OFF" @@ -433,18 +626,11 @@ def f_test(): ] return ["cmake"] + args - def _make_rdkit_cmake(self) -> None: - cmd: List[str] = self._get_cmake_rdkit_cmd_line() - if get_os() == "win": - cmd = [a.replace("\\", "/") for a in cmd] - call_subprocess(cmd) - def _build_rdkit_native(self) -> None: if get_os() == "win": self.run_msbuild("RDKit.sln") else: - cmd = "make -j RDKFuncs".split(" ") - call_subprocess(cmd) + call_subprocess(["make", "-j", "RDKFuncs"]) def _copy_dlls(self) -> None: assert self.build_platform @@ -516,11 +702,21 @@ def _copy_dlls(self) -> None: for path in files_to_copy: shutil.copy2(path, dll_dest_path) + def build_csharp_wrapper(self) -> None: + if get_os() == "win": + self._patch_rdkit_swig_files() + self._prepare_RDKitDotNet_folder() + self._copy_test_projects() + self._build_RDKit2DotNet() + else: + raise RuntimeError("Building wrapper is supported only on Windows.") + def _patch_rdkit_swig_files(self) -> None: # Customize the followings if required. if self.config.swig_patch_enabled: for filepath, patterns in ( ( + # extract BOOST_BINARY self.rdkit_swig_csharp_path / "PropertyPickleOptions.cs", [("BOOST_BINARY\\(\\s*([01]+)\\s*\\)", "0b\\1")], ), @@ -529,7 +725,8 @@ def _patch_rdkit_swig_files(self) -> None: self.rdkit_swig_csharp_path / "RDKFuncs.cs", [ ( - "public static double DiceSimilarity\\([^\\}]*\\.DiceSimilarity__SWIG_(12|13|14)\\([^\\}]*\\}", # NOQA + "public static double DiceSimilarity\\([^\\}]*\\." + "DiceSimilarity__SWIG_(12|13|14)\\([^\\}]*\\}", "", ) ], @@ -558,201 +755,11 @@ def _patch_rdkit_swig_files(self) -> None: self.rdkit_swig_csharp_path, ) - def run_msbuild(self, proj: Union[PathLike, str], platform: Optional[str] = None) -> None: - if not platform: - platform = self.ms_build_platform - cmd = [ - "MSBuild", - str(proj), - f"/p:Configuration=Release,Platform={platform}", - "/maxcpucount", - ] - call_subprocess(cmd) - - def make_zlib(self) -> None: - build_path = self.zlib_path / self.build_dir_name - build_path.mkdir(exist_ok=True) - _curdir = os.path.abspath(os.curdir) - try: - os.chdir(build_path) - cmd = ["cmake", str(self.zlib_path)] + list(self.g_option_of_cmake) - call_subprocess(cmd) - self.run_msbuild("zlib.sln") - shutil.copy2(build_path / "zconf.h", self.zlib_path) - finally: - os.chdir(_curdir) - - def make_libpng(self) -> None: - build_path = self.libpng_path / self.build_dir_name - build_path.mkdir(exist_ok=True) - _curdir = os.path.abspath(os.curdir) - try: - os.chdir(build_path) - cmd = ( - "cmake " - + f"{str(self.libpng_path)} " - + f"{self.g_option_of_cmake} " - + f'-DZLIB_LIBRARY="{str(self.zlib_path / self.build_dir_name / "Release" / "zlib.lib")}" ' # NOQA - + f'-DZLIB_INCLUDE_DIR="{str(self.zlib_path)}" ' - + "-DPNG_SHARED=ON " - + "-DPNG_STATIC=OFF " - ) - call_subprocess(cmd) - self.run_msbuild("libpng.sln") - finally: - os.chdir(_curdir) - - def vs15_proj_to_vs16(self, proj_file: Path) -> None: - _V = "VCProjectVersion" - _P = "PlatformToolset" - replace_file_string( - proj_file, - [ - (f"\\<{_V}>15\\.0\\<\\/{_V}\\>", f"<{_V}>{get_vs_ver()}",), - ( - f"\\<{_P}\\>v141\\<\\/{_P}\\>", - f"<{_P}>v{get_msvc_internal_ver().replace('.', '')}", - ), - ], - ) - - def make_pixman(self) -> None: - _curdir = os.path.abspath(os.curdir) - try: - proj_dir = self.pixman_path / "vc2017" - proj_dir.mkdir(exist_ok=True) - os.chdir(proj_dir) - files_dir = self.this_path / "files" / "pixman" - vcxproj = "pixman.vcxproj" - shutil.copy2(files_dir / vcxproj, proj_dir) - proj_file = proj_dir / vcxproj - shutil.copy2(files_dir / "config.h", self.pixman_path / "pixman") - - self.vs15_proj_to_vs16(proj_file) - - makefile_win32 = self.pixman_path / "pixman" / "Makefile.win32" - makefile_sources = self.pixman_path / "pixman" / "Makefile.sources" - - c_files: List[str] = [] - i_files: List[str] = [] - - pattern_c = re.compile("^libpixman_sources\\s*\\=(?P.*)$") - pattern_h = re.compile("^libpixman_headers\\s*\\=(?P.*)$") - for line in makefile_to_lines(makefile_sources): - match_and_add(pattern_c, c_files, line) - match_and_add(pattern_h, i_files, line) - - pattern_c = re.compile("^\\s*libpixman_sources\\s*\\+\\=(?P.*)$") - for line in makefile_to_lines(makefile_win32): - match_and_add(pattern_c, c_files, line) - - tree = load_msbuild_xml(proj_file) - root = tree.getroot() - item_group = SubElement(root, "ItemGroup") - for name in c_files: - node = SubElement(item_group, "ClCompile") - node.attrib["Include"] = f"..\\pixman\\{name}" - for name in i_files: - node = SubElement(item_group, "ClInclude") - node.attrib["Include"] = f"..\\pixman\\{name}" - - tree.write(proj_file, "utf-8", True) - self.run_msbuild(proj_file) - finally: - os.chdir(_curdir) - - def make_cairo(self) -> None: - # TODO: get file names from src\Makefile.sources - _curdir = os.path.abspath(os.curdir) - try: - proj_dir = self.cairo_path / "vc2017" - proj_dir.mkdir(exist_ok=True) - os.chdir(proj_dir) - files_dir = self.this_path / "files" / "cairo" - vcxproj = "cairo.vcxproj" - shutil.copy2(files_dir / vcxproj, proj_dir) - proj_file = proj_dir / vcxproj - shutil.copy2(files_dir / "cairo-features.h", self.cairo_path / "src") - self.vs15_proj_to_vs16(proj_file) - replace_file_string( - proj_file, - [ - ("__CAIRODIR__", str(self.cairo_path).replace("\\", "\\\\"),), - ("__LIBPNGDIR__", str(self.libpng_path).replace("\\", "\\\\"),), - ("__ZLIBDIR__", str(self.zlib_path).replace("\\", "\\\\"),), - ("__PIXMANDIR__", str(self.pixman_path).replace("\\", "\\\\"),), - ("__FREETYPEDIR__", str(self.freetype_path).replace("\\", "\\\\"),), - ], - ) - self.run_msbuild(vcxproj) - finally: - os.chdir(_curdir) - - def make_freetype(self) -> None: - _curdir = os.path.abspath(os.curdir) - try: - os.chdir(self.freetype_path) - shutil.copy2( - self.this_path / "files" / "freetype" / "freetype.vcxproj", - self.freetype_path / "builds" / "windows" / "vc2010", - ) - os.chdir(self.freetype_path / "builds" / "windows" / "vc2010") - logging.debug(f"current dir = {os.getcwd()}") - self.run_msbuild("freetype.sln") - finally: - os.chdir(_curdir) - - @property - def path_GraphMolCSharp_i(self): - return self.rdkit_csharp_wrapper_path / "GraphMolCSharp.i" - - @property - def path_MolDraw2D_i(self): - return self.rdkit_path / "Code" / "JavaWrappers" / "MolDraw2D.i" - - def build_rdkit(self) -> None: - self.rdkit_csharp_build_path.mkdir(exist_ok=True) - _curdir = os.path.abspath(os.curdir) - os.chdir(self.rdkit_csharp_build_path) - try: - if self.config.swig_patch_enabled: - replace_file_string( - self.path_GraphMolCSharp_i, - [("boost::int32_t", "int32_t",), ("boost::uint32_t", "uint32_t",),], - make_backup=True, - ) - if self.config.cairo_support: - insert_line_after( - self.path_MolDraw2D_i, - { - r"#include ": r"#include ", # NOQA - r"%include ": r"%include ", # NOQA - }, - make_backup=True, - ) - self._make_rdkit_cmake() - self._build_rdkit_native() - self._copy_dlls() - finally: - os.chdir(_curdir) - - @property - def path_RDKit2DotNet_folder(self): - return self.rdkit_csharp_wrapper_path / "RDKit2DotNet" - - def build_csharp_wrapper(self) -> None: - if get_os() == "win": - self._win_build_csharp_wrapper() - else: - raise RuntimeError("Building wrapper is supported only on Windows.") - - def _win_build_csharp_wrapper(self) -> None: - self._patch_rdkit_swig_files() + def _prepare_RDKitDotNet_folder(self): remove_if_exist(self.path_RDKit2DotNet_folder) - self.path_RDKit2DotNet_folder.mkdir() - shutil.copy2( - self.this_path / "files" / "rdkit" / "RDKit2DotNet.csproj", - self.path_RDKit2DotNet_folder, + shutil.copytree( + self.this_path / "files" / "rdkit" / "RDKit2DotNet", + self.rdkit_csharp_wrapper_path / "RDKit2DotNet", ) path_RDKit2DotNet_csproj = self.path_RDKit2DotNet_folder / "RDKit2DotNet.csproj" rdkit_dotnetwrap_version = self.get_version_for_rdkit_dotnetwrap() @@ -769,10 +776,8 @@ def _win_build_csharp_wrapper(self) -> None: ), ], ) - tree = load_msbuild_xml(path_RDKit2DotNet_csproj) project = tree.getroot() - property_group = SubElement(project, "PropertyGroup") sign_assembly = SubElement(property_group, "SignAssembly") sign_assembly.text = "true" @@ -785,26 +790,59 @@ def _win_build_csharp_wrapper(self) -> None: for filename in glob.glob( str(self.rdkit_csharp_wrapper_path / get_os() / cpu_model / "*.dll") ): - basename = os.path.basename(filename) + dllbasename = os.path.basename(filename) content = SubElement(item_group, "None") - content.attrib["Include"] = f"..\\\\{get_os()}\\\\{cpu_model}\\\\{basename}" - content.attrib["Link"] = f"{get_os()}\\\\{cpu_model}\\\\{basename}" + path_to_dll = f"..\\\\{get_os()}\\\\{cpu_model}\\\\{dllbasename}" + link_to_dll = f"runtimes\\\\{get_os()}-{cpu_model}\\\\native\\\\{dllbasename}" + content.attrib["Include"] = path_to_dll + content.attrib["Link"] = link_to_dll copy_to_output_directory = SubElement(content, "CopyToOutputDirectory") copy_to_output_directory.text = "PreserveNewest" - tree.write(path_RDKit2DotNet_csproj, "utf-8", True) - path_rdkit_files = self.this_path / "files" / "rdkit" - shutil.copy2(path_rdkit_files / "rdkit2dotnet.snk", self.path_RDKit2DotNet_folder) - remove_if_exist(self.rdkit_csharp_wrapper_path / "RDKit2DotNetTest") - shutil.copytree( - path_rdkit_files / "RDKit2DotNetTest", - self.rdkit_csharp_wrapper_path / "RDKit2DotNetTest", + @property + def test_csprojects(self) -> Collection[str]: + return ( + "RDKit2DotNetTest", + "RDKit2DotNetTest2", + "NuGetExample", + "NuGetExample2", ) - shutil.copy2(path_rdkit_files / "RDKit2DotNet.sln", self.rdkit_csharp_wrapper_path) - logging.info(f"{self.rdkit_csharp_wrapper_path / 'RDKit2DotNet.sln'} is created.") + @property + def test_sln_names(self) -> Collection[str]: + return ( + "RDKit2DotNet.sln", + "NuGetExample.sln", + ) + def _copy_test_projects(self): + path_rdkit_files = self.this_path / "files" / "rdkit" + for name in self.test_csprojects: + remove_if_exist(self.rdkit_csharp_wrapper_path / name) + shutil.copytree( + path_rdkit_files / name, self.rdkit_csharp_wrapper_path / name, dirs_exist_ok=True, + ) + replace_file_string( + self.rdkit_csharp_wrapper_path / name / f"{name}.csproj", + [ + ( + r"\", + '', + ) + ], + ) + for name in self.test_sln_names: + shutil.copy2(path_rdkit_files / name, self.rdkit_csharp_wrapper_path) + print(f"Test slns {self.test_sln_names} are created in {self.rdkit_csharp_wrapper_path}.") + print("RDKit2DotNetTest: .NET 5.0 example.") + print("RDKit2DotNetTest2: .NET Framework 4 example.") + print("NuGetExample: NuGet package example for .NET 5.0.") + print("NuGetExample2: NuGet package example for .NET Framework 4.") + + def _build_RDKit2DotNet(self): _pushd_build_wrapper = os.getcwd() try: os.chdir(self.path_RDKit2DotNet_folder) @@ -816,10 +854,13 @@ def _win_build_csharp_wrapper(self) -> None: os.chdir(_pushd_build_wrapper) def build_nuget_package(self) -> None: - _os: SupportedSystem + dll_basenames_dic = self._make_dll_basenames_dic() + self._prepare_nuspec(dll_basenames_dic) + self._prepare_targets_file(dll_basenames_dic) + self._build_nupkg() + def _make_dll_basenames_dic(self) -> Mapping[str, Mapping[str, Sequence[str]]]: dll_basenames_dic: Dict[str, Dict[str, List[str]]] = dict() - for _os in typing.get_args(SupportedSystem): if _os not in dll_basenames_dic: dll_basenames_dic[_os] = dict() @@ -833,14 +874,13 @@ def build_nuget_package(self) -> None: assert dll_basenames_dic["win"]["x64"] assert dll_basenames_dic["linux"]["x64"] assert not dll_basenames_dic["linux"]["x86"] + return dll_basenames_dic - # Prepare RDKit2DotNet.nuspec - + def _prepare_nuspec(self, dll_basenames_dic: Mapping[str, Mapping[str, Sequence[str]]]): nuspec_file = shutil.copy2( self.this_path / "files" / "rdkit" / f"{project_name}.nuspec", self.rdkit_csharp_wrapper_path, ) - # RDKit Release_0000_00_0, Boost 0.0.0, FreeType 0.0.0, and Eigen 0.0.0 lib_versions: List[str] = [ f"Boost {self.get_version_for_boost()}", @@ -866,29 +906,27 @@ def build_nuget_package(self) -> None: ("__VISUALSTUDIOVERSION__", f"{get_vs_ver()}",), ], ) - + # write native file info to nuspec file. nuspec_dlls_spec = [] for _os in typing.get_args(SupportedSystem): for cpu_model in typing.get_args(CpuModel): for dll_basename in dll_basenames_dic[_os][cpu_model]: nuspec_dlls_spec.append( f'\n' + f'target="runtimes/{_os}-{cpu_model}/native/{dll_basename}" />\n' ) - replace_file_string(nuspec_file, [("\\", "".join(nuspec_dlls_spec))]) + def _prepare_targets_file(self, dll_basenames_dic: Mapping[str, Mapping[str, Sequence[str]]]): targets_file = shutil.copy2( self.this_path / "files" / "rdkit" / f"{project_name}.targets", self.rdkit_csharp_wrapper_path, ) - non_net = ( "!$(TargetFramework.Contains('netstandard')) " "And !$(TargetFramework.Contains('netcoreapp')) " "And !$(TargetFramework.Contains('net5'))" ) - targets_dlls_spec: List[str] = [] _os = "win" for cpu_model in typing.get_args(CpuModel): @@ -906,11 +944,9 @@ def build_nuget_package(self) -> None: ) targets_dlls_spec.append("\\n") targets_dlls_spec.append("\\n") - targets_dlls_spec.append( f"\\n" ) - _os = "win" for cpu_model in typing.get_args(CpuModel): for dllname in dll_basenames_dic[_os][cpu_model]: @@ -918,17 +954,19 @@ def build_nuget_package(self) -> None: f'\\n' ) - targets_dlls_spec.append(f"{cpu_model}/{dllname}\\n") + targets_dlls_spec.append( + f"runtimes/{_os}-{cpu_model}/native/{dllname}\\n" + ) targets_dlls_spec.append( "PreserveNewest\\n" ) targets_dlls_spec.append("\\n") - targets_dlls_spec.append("") replace_file_string( targets_file, [("\\", "".join(targets_dlls_spec))] ) + def _build_nupkg(self): _curr_dir = os.curdir os.chdir(self.rdkit_csharp_wrapper_path) try: @@ -946,12 +984,23 @@ def build_nuget_package(self) -> None: def clean(self): if self.config.rdkit_path: - for p in [ - f"{project_name}.nuspec", - f"{project_name}.targets", - "swig_csharp", - "Properties", - ] + list(typing.get_args(SupportedSystem)): + for path in ( + self.path_GraphMolCSharp_i, + self.path_MolDraw2D_i, + ): + make_or_restore_bak(path) + for p in ( + [ + f"{project_name}.nuspec", + f"{project_name}.targets", + "swig_csharp", + "Properties", + "packages", + ] + + list(typing.get_args(SupportedSystem)) + + list(self.test_csprojects) + + list(self.test_sln_names) + ): remove_if_exist(self.rdkit_csharp_wrapper_path / p) remove_if_exist(self.rdkit_path / "lib") for _os in typing.get_args(SupportedSystem): @@ -971,12 +1020,6 @@ def clean(self): remove_if_exist(self.pixman_path / "vc2017") if self.config.cairo_path: remove_if_exist(self.cairo_path / "vc2017") - for path in ( - self.path_RDKit2DotNet_folder, - self.path_GraphMolCSharp_i, - self.path_MolDraw2D_i, - ): - make_or_restore_bak(path) def main() -> None: diff --git a/files/rdkit/NuGetExample.sln b/files/rdkit/NuGetExample.sln new file mode 100644 index 0000000..b715777 --- /dev/null +++ b/files/rdkit/NuGetExample.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NuGetExample", "NuGetExample\NuGetExample.csproj", "{A10F2BB4-92DE-428A-9E26-8B65D2F589B2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NuGetExample2", "NuGetExample2\NuGetExample2.csproj", "{E727FFA2-B4B7-467A-9F36-0669D1688A12}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|x64.ActiveCfg = Debug|x64 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|x64.Build.0 = Debug|x64 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|x86.ActiveCfg = Debug|x86 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Debug|x86.Build.0 = Debug|x86 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|Any CPU.Build.0 = Release|Any CPU + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|x64.ActiveCfg = Release|x64 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|x64.Build.0 = Release|x64 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|x86.ActiveCfg = Release|x86 + {A10F2BB4-92DE-428A-9E26-8B65D2F589B2}.Release|x86.Build.0 = Release|x86 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|x64.ActiveCfg = Debug|x64 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|x64.Build.0 = Debug|x64 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|x86.ActiveCfg = Debug|x86 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Debug|x86.Build.0 = Debug|x86 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|Any CPU.Build.0 = Release|Any CPU + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|x64.ActiveCfg = Release|x64 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|x64.Build.0 = Release|x64 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|x86.ActiveCfg = Release|x86 + {E727FFA2-B4B7-467A-9F36-0669D1688A12}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E87277B8-C35A-44F9-80BF-F0DAB348D76D} + EndGlobalSection +EndGlobal diff --git a/files/rdkit/NuGetExample/NuGetExample.csproj b/files/rdkit/NuGetExample/NuGetExample.csproj new file mode 100644 index 0000000..6377d3f --- /dev/null +++ b/files/rdkit/NuGetExample/NuGetExample.csproj @@ -0,0 +1,39 @@ + + + + Exe + net5.0 + AnyCPU;x64;x86 + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/files/rdkit/NuGetExample2/NuGetExample2.csproj b/files/rdkit/NuGetExample2/NuGetExample2.csproj new file mode 100644 index 0000000..9700220 --- /dev/null +++ b/files/rdkit/NuGetExample2/NuGetExample2.csproj @@ -0,0 +1,51 @@ + + + + Exe + net40 + AnyCPU;x64;x86 + + + + AnyCPU + + + + x86 + + + + x64 + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/files/rdkit/RDKFuncsPINVOKE_Loader.cs b/files/rdkit/RDKFuncsPINVOKE_Loader.cs index 57a0d5b..54c5091 100644 --- a/files/rdkit/RDKFuncsPINVOKE_Loader.cs +++ b/files/rdkit/RDKFuncsPINVOKE_Loader.cs @@ -6,6 +6,7 @@ namespace GraphMolWrap { partial class RDKFuncsPINVOKE { +#if NETFRAMEWORK private const string ModuleName = "RDKFuncs"; [System.Security.SuppressUnmanagedCodeSecurity] @@ -14,43 +15,41 @@ internal static class UnsafeNativeMethods [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool SetDllDirectory(string lpPathName); } +#endif internal static void LoadDll() { +#if NETFRAMEWORK var os = Environment.OSVersion; switch (os.Platform) { case PlatformID.Win32NT: const string DllFileName = ModuleName + ".dll"; - var _subdir = Environment.Is64BitProcess ? "x64" : "x86"; + var cpu = Environment.Is64BitProcess ? "x64" : "x86"; var executingAsm = System.Reflection.Assembly.GetExecutingAssembly(); - foreach (var ss in new[] { null, "nt"}) + foreach (var subdir in new[] { + cpu, + Path.Combine("runtimes", $"win-{cpu}", "native"), + }) { - var subdir = ss == null ? _subdir : Path.Combine("nt", _subdir); + if (SetDllDirectoryIfFileExist(Path.GetDirectoryName(executingAsm.Location), subdir, DllFileName)) + break; + // for ASP.NET + var uri = new Uri(executingAsm.CodeBase); + if (uri.Scheme == "file") { - var currPath = Path.GetDirectoryName(executingAsm.Location); - if (SetDllDirectoryIfFileExist(currPath, subdir, DllFileName)) - goto L_Found; - } - { - // for ASP.NET - var uri = new Uri(executingAsm.CodeBase); - if (uri.Scheme == "file") - { - var currPath = Path.GetDirectoryName(uri.AbsolutePath); - if (SetDllDirectoryIfFileExist(currPath, subdir, DllFileName)) - goto L_Found; - } + if (SetDllDirectoryIfFileExist(Path.GetDirectoryName(uri.AbsolutePath), subdir, DllFileName)) + break; } } - - L_Found: break; default: break; } +#endif } +#if NETFRAMEWORK /// /// SetDllDirectory if // or /exists. /// @@ -60,11 +59,8 @@ internal static void LoadDll() /// if file exists and set it. private static bool SetDllDirectoryIfFileExist(string directoryName, string subdir, string dllName) { - if (subdir != null) - { - if (SetDllDirectoryIfFileExist(Path.Combine(directoryName, subdir), dllName)) - return true; - } + if (SetDllDirectoryIfFileExist(Path.Combine(directoryName, subdir), dllName)) + return true; if (SetDllDirectoryIfFileExist(directoryName, dllName)) return true; @@ -88,6 +84,7 @@ private static bool SetDllDirectoryIfFileExist(string directoryName, string dllN return true; } return false; - } + } +#endif } } diff --git a/files/rdkit/RDKit2DotNet.sln b/files/rdkit/RDKit2DotNet.sln index e0f3e0a..5010235 100644 --- a/files/rdkit/RDKit2DotNet.sln +++ b/files/rdkit/RDKit2DotNet.sln @@ -5,42 +5,28 @@ VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RDKit2DotNet", "RDKit2DotNet\RDKit2DotNet.csproj", "{D6166F1C-DCD1-4E57-B002-4B6869130E43}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDKit2DotNetTest", "RDKit2DotNetTest\RDKit2DotNetTest.csproj", "{E7DF7657-90D6-4C7F-A430-A48737C049B2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RDKit2DotNetTest", "RDKit2DotNetTest\RDKit2DotNetTest.csproj", "{E7DF7657-90D6-4C7F-A430-A48737C049B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RDKit2DotNetTest2", "RDKit2DotNetTest2\RDKit2DotNetTest2.csproj", "{4FF1CAED-C58F-43D0-A5CA-24959A52B9CB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|x64.ActiveCfg = Debug|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|x64.Build.0 = Debug|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|x86.ActiveCfg = Debug|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Debug|x86.Build.0 = Debug|Any CPU {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|Any CPU.ActiveCfg = Release|Any CPU {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|Any CPU.Build.0 = Release|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|x64.ActiveCfg = Release|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|x64.Build.0 = Release|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|x86.ActiveCfg = Release|Any CPU - {D6166F1C-DCD1-4E57-B002-4B6869130E43}.Release|x86.Build.0 = Release|Any CPU {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|x64.ActiveCfg = Debug|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|x64.Build.0 = Debug|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|x86.ActiveCfg = Debug|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Debug|x86.Build.0 = Debug|Any CPU {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|Any CPU.Build.0 = Release|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|x64.ActiveCfg = Release|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|x64.Build.0 = Release|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|x86.ActiveCfg = Release|Any CPU - {E7DF7657-90D6-4C7F-A430-A48737C049B2}.Release|x86.Build.0 = Release|Any CPU + {4FF1CAED-C58F-43D0-A5CA-24959A52B9CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FF1CAED-C58F-43D0-A5CA-24959A52B9CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FF1CAED-C58F-43D0-A5CA-24959A52B9CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FF1CAED-C58F-43D0-A5CA-24959A52B9CB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/files/rdkit/RDKit2DotNet.csproj b/files/rdkit/RDKit2DotNet/RDKit2DotNet.csproj similarity index 100% rename from files/rdkit/RDKit2DotNet.csproj rename to files/rdkit/RDKit2DotNet/RDKit2DotNet.csproj diff --git a/files/rdkit/rdkit2dotnet.snk b/files/rdkit/RDKit2DotNet/rdkit2dotnet.snk similarity index 100% rename from files/rdkit/rdkit2dotnet.snk rename to files/rdkit/RDKit2DotNet/rdkit2dotnet.snk diff --git a/files/rdkit/RDKit2DotNetTest/RDKit2DotNetTest.csproj b/files/rdkit/RDKit2DotNetTest/RDKit2DotNetTest.csproj index 0f7d89a..592cfe7 100644 --- a/files/rdkit/RDKit2DotNetTest/RDKit2DotNetTest.csproj +++ b/files/rdkit/RDKit2DotNetTest/RDKit2DotNetTest.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp3.1 + net5.0 diff --git a/files/rdkit/RDKit2DotNetTest2/RDKit2DotNetTest2.csproj b/files/rdkit/RDKit2DotNetTest2/RDKit2DotNetTest2.csproj new file mode 100644 index 0000000..ccf98a9 --- /dev/null +++ b/files/rdkit/RDKit2DotNetTest2/RDKit2DotNetTest2.csproj @@ -0,0 +1,34 @@ + + + + Exe + net40 + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + +