{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "<script async src=\"https://www.googletagmanager.com/gtag/js?id=UA-59152712-8\"></script>\n", "<script>\n", " window.dataLayer = window.dataLayer || [];\n", " function gtag(){dataLayer.push(arguments);}\n", " gtag('js', new Date());\n", "\n", " gtag('config', 'UA-59152712-8');\n", "</script>\n", "\n", "# BlackHoles@Home Tutorial: Compiling the `BOINC` libraries\n", "\n", "## Author: Leo Werneck\n", "\n", "## This tutorial notebook demonstrates how to compile the `BOINC` libraries on different platforms\n", "\n", "## Introduction:\n", "\n", "The [BlackHoles@Home](http://blackholesathome.net/) project allows users to volunteer CPU time so a large number of binary black holes simulations can be performed. The objective is to create a large catalog of [gravitational waveforms](https://en.wikipedia.org/wiki/Gravitational_wave), which can be used by observatories such as [LIGO](https://www.ligo.org), [VIRGO](https://www.virgo-gw.eu), and, in the future, [LISA](https://lisa.nasa.gov) in order to infer what was the source of a detected gravitational wave.\n", "\n", "BlackHoles@Home is destined to run on the [BOINC](https://boinc.berkeley.edu) infrastructure (alongside [Einstein@Home](https://einsteinathome.org/) and [many other great projects](https://boinc.berkeley.edu/projects.php)), enabling anyone with a computer to contribute to the construction of the largest numerical relativity gravitational wave catalogs ever produced.\n", "\n", "### Additional Reading Material:\n", "\n", "* [BOINC's Wiki page](https://boinc.berkeley.edu/trac/wiki)\n", "* [Debian's Wiki BOINC server guide](https://wiki.debian.org/BOINC/ServerGuide/Initialisation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='toc'></a>\n", "\n", "# Table of Contents\n", "$$\\label{toc}$$\n", "\n", "This tutorial compiles the `BOINC` libraries. It will also install all needed dependencies. We test everything is okay by compiling and running a simple \"Hello World!\" application that makes use of the `BOINC` libraries. This tutorial is organized as follows:\n", "\n", "1. [Step 1](#loading_python_nrpy_modules): Loading necessary Python/NRPy+ modules\n", "1. [Step 2](#compilation_script): A simple script to compile the `BOINC` libraries\n", "1. [Step 3](#compilating_boinc_libraries): Compiling the `BOINC` libraries\n", "1. [Step 4](#compilation_test): Compiling a simple program\n", "1. [Step 5](#latex_pdf_output): Output this notebook to $\\LaTeX$-formatted PDF file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='loading_python_nrpy_modules'></a>\n", "\n", "# Step 1: Loading needed Python/NRPy+ modules \\[Back to [top](#toc)\\]\n", "$$\\label{loading_python_nrpy_modules}$$\n", "\n", "We start by loading the necessary Python/NRPy+ moduels used by this tutorial notebook. We also set up the `BOINC` directory path (the default path is the current working directory)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Step 1: Import necessary modules - set directories.\n", "# Step 1.a: Import required Python modules\n", "import os,sys,shutil\n", "\n", "# Step 1.b: Add NRPy's root directory to the sys.path()\n", "sys.path.append(\"..\")\n", "\n", "# Step 1.c: Load NRPy+'s command line helper module\n", "import cmdline_helper as cmd\n", "\n", "# Step 1.d: Set directories needed by this tutorial notebook\n", "boinc_base_dir = \"/Users/werneck/bhah\" # os.getcwd()\n", "boinc_root_dir = os.path.join(boinc_base_dir,\"boinc\")\n", "boinc_lib_dir = os.path.join(boinc_root_dir,\"lib\")\n", "boinc_api_dir = os.path.join(boinc_root_dir,\"api\")\n", "boinc_zip_dir = os.path.join(boinc_root_dir,\"zip\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='compilation_script'></a>\n", "\n", "# Step 2: A simple script to compile the `BOINC` libraries \\[Back to [top](#toc)\\]\n", "$$\\label{compilation_script}$$\n", "\n", "We will now write a simple `bash` script that will take care of downloading the `BOINC` source code and compiling the `BOINC` libraries.\n", "\n", "The script performs the following tasks:\n", "\n", "1. Install the necessary dependencies.\n", "1. Download the [`BOINC` source code](https://github.com/BOINC/boinc) (if necessary).\n", "1. Compile the `BOINC` core, api, and zip libraries.\n", "\n", "The `BOINC` library require the following packages:\n", "\n", "1. git\n", "1. make\n", "1. m4\n", "1. autoconf\n", "1. libtool\n", "1. A C++ compiler\n", "\n", "In Linux, we will be using the [GNU compilers](https://gcc.gnu.org) installed using [`aptitude`](http://manpages.ubuntu.com/manpages/bionic/man8/aptitude-curses.8.html) in Ubuntu and Debian. In Mac OS X, we will be using the [LLVM compilers](https://llvm.org) installed using [`homebrew`](https://brew.sh)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Step 2: Write down a script to compile the BOINC libraries\n", "# Step 2.a: Check the platform. This will adjust the way we install the dependencies.\n", "platform = sys.platform\n", "compiler_config = \"\"\n", "if platform == \"linux\":\n", " # In Ubuntu/Debian, use aptitude to install the dependencies.\n", " # To avoid issues where the user does not have sudo priviledges,\n", " # such as in mybinder, we check if we find the command first.\n", " dependency_list = [\"git\",\"make\",\"m4\",\"autoconf\",\"libtool\",\"g++\"]\n", " dependencies = \"\"\n", " for dependency in dependency_list:\n", " path = shutil.which(dependency)\n", " if path is not None:\n", " dependencies += dependency+\" \"\n", " else:\n", " print(dependency+\" found at \"+path)\n", " \n", " if dependencies != \"\":\n", " install_dependencies = \"sudo apt install -y \"+dependencies\n", "elif platform == \"darwin\":\n", " # In Mac OS X, use homebrew to install the dependencies.\n", " install_dependencies = \"brew install git make m4 autoconf libtool llvm\"\n", " # Because we use clang/clang++ instead of gcc/g++, we need\n", " # to specify additional compilation flags to help the build\n", " # script locate all the header files and libraries we will\n", " # need. The paths below assume that the llvm compilers are\n", " # in the default brew path /usr/local/opt. Adjust the\n", " # variable 'path_to_llvm' if that's not the case.\n", " path_to_llvm = \"/usr/local/opt/llvm/\"\n", " path_to_clang = os.path.join(path_to_llvm,\"bin\",\"clang\")\n", " path_to_clangpp = os.path.join(path_to_llvm,\"bin\",\"clang++\")\n", " path_to_clang_include = os.path.join(path_to_llvm,\"include\")\n", " path_to_clang_library = os.path.join(path_to_llvm,\"lib\")\n", " CPPFLAGS = \"-I%s\"%(path_to_clang_include)\n", " LDFLAGS = \"-L%s\"%(path_to_clang_library)\n", " compiler_config = \"CC=%s CXX=%s OBJC=%s CPPFLAGS=\\\"%s\\\" LDFLAGS=\\\"%s\\\" \"%(path_to_clang,\n", " path_to_clangpp,\n", " path_to_clang,\n", " path_to_clang_include,\n", " path_to_clang_library)\n", "else:\n", " print(\"Error: platform %s is currently not supported.\"%platform)\n", " sys.exit(1)\n", " \n", "with open(\"compile_BOINC_libraries.sh\",\"w\") as file:\n", " file.write(r\"\"\"#!/bin/bash\n", "\n", "# Install all required software\n", "%s\n", "\n", "# Download BOINC repository (if necessary)\n", "boincdir=%s\n", "if [ -d \"$boincdir\" ]; then\n", " echo \"BOINC directory found at $boincdir\"\n", "else\n", " echo \"BOINC directory not found at $boincdir. Cloning from BOINC github repository...\"\n", " git clone https://github.com/BOINC/boinc boinc\n", "fi\n", "\n", "# Now change directories to the BOINC directory\n", "cd \"$boincdir\"\n", "\n", "# Compile the core BOINC libraries\n", "./_autosetup -f\n", "%s./configure --disable-client --disable-manager --disable-server\n", "make\n", "\n", "# Now compile the boinc_zip library\n", "cd %s\n", "make\n", "\"\"\"%(install_dependencies,boinc_root_dir,compiler_config,boinc_zip_dir))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='compilating_boinc_libraries'></a>\n", "\n", "# Step 3: Compiling the `BOINC` libraries \\[Back to [top](#toc)\\]\n", "$$\\label{compilating_boinc_libraries}$$\n", "\n", "We now run the script above to compile the `BOINC` libraries. This tutorial notebook has been tested in the following systems:\n", "\n", "1. Ubuntu 20.04 LTS.\n", "1. Mac OS X Big Sur (version 11.2.3).\n", "\n", "If all the dependencies are already installed, then the script should finish running in just a few minutes. If not, then it will download the dependencies and the execution time may vary depending on your internet connection speed." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Now compiling BOINC libraries (can take a few minutes depending on your internet connection) ...\n", "Finished compiling BOINC libraries\n" ] } ], "source": [ "# Step 3: Compile the BOINC libraries\n", "# FIXME: I don't think this is the best way of doing this.\n", "print(\"Now compiling BOINC libraries (can take a few minutes depending on your internet connection) ...\")\n", "status = os.system(\"source compile_BOINC_libraries.sh\")\n", "print(\"Finished compiling BOINC libraries\" if status == 0 \n", " else \"Error: Something went wrong when compiling the BOINC libraries.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='compilation_test'></a>\n", "\n", "# Step 4: Compiling a simple program \\[Back to [top](#toc)\\]\n", "$$\\label{compilation_test}$$\n", "\n", "We now compile a \"Hello World!\" program that makes use of the `BOINC` libraries. This will help us know if everything is okay with the compilation of the libraries." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running hello_boinc program...\n", "Hello BOINC!\n", "All done!\n" ] } ], "source": [ "# Step 3: Compiling a test program\n", "# Step 3.a: Write down a \"Hello World!\" program that uses the BOINC libraries\n", "outfile = \"hello_boinc.cpp\"\n", "with open(outfile,\"w\") as file:\n", " file.write(r\"\"\"\n", "// Core C++ input/output header\n", "#include <iostream>\n", "\n", "// BOINC API header\n", "#include \"boinc_api.h\"\n", "\n", "// Main program\n", "int main(int argc, char** argv) {\n", "\n", " // Initialize the boinc environment\n", " int status = boinc_init();\n", " \n", " // Check everything is okay\n", " if( status != 0 ) {\n", " fprintf(stderr,\"Error: boinc_init() returned a non-zero value: %d. Terminating.\",status);\n", " boinc_finish(status);\n", " }\n", " \n", " // Print a message to the user\n", " printf(\"Hello BOINC!\\n\");\n", " \n", " // Terminate the program with no errors\n", " boinc_finish(0);\n", " \n", " // All done!\n", "}\n", "\"\"\")\n", "\n", "# Step 3.b: Add the base nrpytutorial directory to sys.path()\n", "import sys\n", "sys.path.append('..')\n", "\n", "# Step 3.c: Import the cmdline_helper NRPy+ module\n", "import cmdline_helper as cmd\n", "\n", "# Step 3.d: Prepare to compile\n", "# Step 3.d.i: Set the C++ compiler flags\n", "CXXFLAGS = \"-I%s -I%s \"%(boinc_api_dir,boinc_lib_dir)\n", "LDFLAGS = \"-L%s -L%s -lboinc_api -lboinc \"%(boinc_api_dir,boinc_lib_dir)\n", "\n", "# Step 3.d.ii: Set the C++ compiler\n", "if platform == 'linux':\n", " CXX_compiler = \"g++ \"\n", "elif platform == 'darwin':\n", " CXX_compiler = \"clang++ \"\n", " CXXFLAGS += \"-I%s \"%(path_to_clang_include)\n", " LDFLAGS += \"-L%s \"%(path_to_clang_library)\n", "else:\n", " print(\"Error: platform %s is currently not supported.\"%platform)\n", " sys.exit(1)\n", "\n", "# Step 3.d.iii: Compile the program\n", "CXX_compile_string = CXX_compiler+CXXFLAGS+\"hello_boinc.cpp -o hello_boinc \"+LDFLAGS\n", "os.system(CXX_compile_string)\n", "\n", "# Step 3.d.iv: Run the program\n", "print(\"Running hello_boinc program...\")\n", "!./hello_boinc\n", "print(\"All done!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id='latex_pdf_output'></a>\n", "\n", "# Step 5: Output this notebook to $\\LaTeX$-formatted PDF file \\[Back to [top](#toc)\\]\n", "$$\\label{latex_pdf_output}$$\n", "\n", "The following code cell converts this Jupyter notebook into a proper, clickable $\\LaTeX$-formatted PDF file. After the cell is successfully run, the generated PDF may be found in the root NRPy+ tutorial directory, with filename\n", "[Tutorial-BlackHolesAtHome-Compiling_the_BOINC_libraries.pdf](Tutorial-BlackHolesAtHome-Compiling_the_BOINC_libraries.pdf) (Note that clicking on this link may not work; you may need to open the PDF file through another means.)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2021-03-07T17:21:21.309338Z", "iopub.status.busy": "2021-03-07T17:21:21.308582Z", "iopub.status.idle": "2021-03-07T17:21:24.791779Z", "shell.execute_reply": "2021-03-07T17:21:24.792580Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created Tutorial-BlackHolesAtHome-Compiling_the_BOINC_libraries.tex, and\n", " compiled LaTeX file to PDF file Tutorial-BlackHolesAtHome-\n", " Compiling_the_BOINC_libraries.pdf\n" ] } ], "source": [ "!cp ../latex_nrpy_style.tplx .\n", "cmd.output_Jupyter_notebook_to_LaTeXed_PDF(\"Tutorial-BlackHolesAtHome-Compiling_the_BOINC_libraries\")\n", "!rm -f latex_nrpy_style.tplx" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.2" } }, "nbformat": 4, "nbformat_minor": 2 }