Skip to content

Commit 94238be

Browse files
authored
Merge pull request #210 from vgteam/fix-binder
Fix Binder for GCC 13
2 parents cb898f2 + 35de57e commit 94238be

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

CMakeLists.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,13 @@ target_include_directories(sparsepp INTERFACE "${bdsg_DIR}/deps/sparsepp/")
189189
add_subdirectory("${bdsg_DIR}/deps/mio")
190190

191191
if (BUILD_PYTHON_BINDINGS)
192+
192193
# Binder (because some generated bindings depend on headers packaged with Binder)
194+
# See also: Binder commit defined in make_and_run_binder.py which actually generates bindings.
195+
set(BINDER_COMMIT b6cac94c78ade6c6ffcbda629ffa520561a31788)
193196
ExternalProject_Add(binder
194-
GIT_REPOSITORY "https://github.com/RosettaCommons/binder.git"
195-
GIT_TAG "ee2ecff151d125c3add072a7765aebad6f42a70d"
197+
GIT_REPOSITORY "https://github.com/adamnovak/binder.git"
198+
GIT_TAG "${BINDER_COMMIT}"
196199
# we don't actually build or install Binder via its CMake because we just need its headers
197200
#CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_DIR}
198201
CONFIGURE_COMMAND ""
@@ -202,14 +205,16 @@ if (BUILD_PYTHON_BINDINGS)
202205
set(binder_INCLUDE "${INSTALL_DIR}/${CMAKE_INSTALL_INCLUDEDIR}")
203206

204207
# pybind11
208+
# See also: pybind11 commit defined in make_and_run_binder.py.
209+
set(PYBIND11_COMMIT 5b0a6fc2017fcc176545afe3e09c9f9885283242)
205210
if (CMAKE_MAJOR_VERSION EQUAL "3" AND CMAKE_MINOR_VERSION EQUAL "10")
206211
# We need pybind11 installed in ./pybind11 *before* CMake can finish processing this file.
207212
# On CMake 3.11+ we can do that with FetchContent
208213
# But on CMake 3.10, available on Ubuntu 18.04, we have to just call git ourselves.
209214
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/pybind11")
210215
message(WARNING "Running on CMake without FetchContent_Declare; attempting to download pybind11 manually")
211216
execute_process(COMMAND git clone https://github.com/RosettaCommons/pybind11.git "${PROJECT_SOURCE_DIR}/pybind11")
212-
execute_process(COMMAND git checkout 5b0a6fc2017fcc176545afe3e09c9f9885283242
217+
execute_process(COMMAND git checkout "${PYBIND11_COMMIT}"
213218
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/pybind11")
214219
endif()
215220

@@ -225,7 +230,7 @@ if (BUILD_PYTHON_BINDINGS)
225230
FetchContent_Declare(
226231
pybind11
227232
GIT_REPOSITORY https://github.com/RosettaCommons/pybind11.git
228-
GIT_TAG 5b0a6fc2017fcc176545afe3e09c9f9885283242
233+
GIT_TAG "${PYBIND11_COMMIT}"
229234
)
230235
FetchContent_GetProperties(pybind11)
231236
if (NOT pybind11_POPULATED)

bdsg/include/bdsg/internal/binder_hook_bind.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
// Components needed at binding generation time to make pybind11/Binder work for the library.
55
// Forced to be used as a source for things to bind, even though nothing includes it.
66

7+
// We need to include the OpenMP header with compiler attribute support
8+
// disabled, because Binder can't understand the malloc attribute used in GCC
9+
// 13's omp.h. See <https://github.com/llvm/llvm-project/issues/51607>.
10+
// Do this before anything else can use omp.h.
11+
#define __attribute__(...)
12+
#include <omp.h>
13+
#undef __attribute__
14+
715
#include <string.h>
816

917
#include <vector>

make_and_run_binder.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,31 @@
2323
python_module_name = 'bdsg'
2424

2525
# We have one global notion of what an include looks like
26-
INCLUDE_REGEX = re.compile('^\s*#include\s+(["<])(.*)([">])')
26+
INCLUDE_REGEX = re.compile(r'^\s*#include\s+(["<])(.*)([">])')
2727
# We have one master list of source code extensions
2828
SOURCE_EXTENSIONS = ['hpp', 'cpp', 'h', 'cc', 'c']
2929

3030
def clone_repos():
31-
''' download the most recent copy of binder from git '''
31+
''' download the most correct binder and pybind11 from git '''
3232
if not glob.glob("binder"):
3333
print("Binder not found, cloning repo...")
34-
subprocess.check_call(['git', 'clone', 'https://github.com/RosettaCommons/binder.git', 'binder'])
34+
subprocess.check_call(['git', 'clone', 'https://github.com/adamnovak/binder.git', 'binder'])
3535
parent = os.getcwd()
3636
os.chdir('binder')
37-
subprocess.check_call(['git', 'checkout', 'ee2ecff151d125c3add072a7765aebad6f42a70d'])
37+
# See also: Binder commit defined in CMakeLists.txt for header files.
38+
subprocess.check_call(['git', 'checkout', 'b6cac94c78ade6c6ffcbda629ffa520561a31788'])
3839
os.chdir(parent)
40+
if not glob.glob("binder/build/pybind11"):
41+
print("pybind11 not found, cloning repo...")
42+
parent = os.getcwd()
43+
os.chdir('binder')
44+
os.makedirs('build', exist_ok=True)
45+
subprocess.check_call(['git', 'clone', 'https://github.com/RosettaCommons/pybind11.git', 'build/pybind11'])
46+
os.chdir('build/pybind11')
47+
# See also: pybind11 commit defined in CMakeLists.txt
48+
subprocess.check_call(['git', 'checkout', '5b0a6fc2017fcc176545afe3e09c9f9885283242'])
49+
os.chdir(parent)
50+
3951

4052
def build_binder():
4153
'''
@@ -46,10 +58,19 @@ def build_binder():
4658
'''
4759
if not glob.glob("./build/*/*/bin/*"):
4860
print("Binder not compiled, using packaged build.py...")
49-
# Make Binder use out pybind11 version
50-
subprocess.check_call(['sed', '-i', "s/^_pybind11_version_ = .*/_pybind11_version_ = '5b0a6fc2017fcc176545afe3e09c9f9885283242'/g", 'build.py'])
5161
# TODO: Use CPU counting that accounts for container quotas?
52-
subprocess.check_call([sys.executable, 'build.py', '--jobs', str(multiprocessing.cpu_count())])
62+
subprocess.check_call(
63+
[
64+
sys.executable,
65+
'build.py',
66+
'--compiler',
67+
'clang' if platform.system() == 'Darwin' else 'gcc',
68+
'--jobs',
69+
str(multiprocessing.cpu_count()),
70+
'--pybind11',
71+
os.path.join(os.getcwd(), 'build/pybind11')
72+
]
73+
)
5374
return "binder/" + glob.glob('./build/*/*/bin/')[0] + "binder"
5475

5576
def all_sources_and_headers(include_deps=False):
@@ -228,6 +249,16 @@ def make_bindings_code(all_includes_fn, binder_executable):
228249
# Also make sure to look for libomp from macports or homebrew, like CMakeLists.txt does
229250
command.append('-I/opt/local/include/libomp')
230251
command.append('-I/usr/local/include')
252+
else:
253+
# With current GCC, Clang can't find the multiarch-specific *and*
254+
# GCC-version-specific include path where the OpenMP headers live.
255+
# So help it out.
256+
# TODO: We're assuming we're using GCC.
257+
compiler_version = int(subprocess.check_output(["gcc", "-dumpversion"]).decode('utf-8').split('.')[0])
258+
compiler_triple = subprocess.check_output(["gcc", "-dumpmachine"]).decode('utf-8').strip()
259+
command.append('-I' + f"/usr/lib/gcc/{compiler_triple}/{compiler_version}/include")
260+
# We rely on macro hacks in binder_hook_bind.hpp to translate the file
261+
# into something Binder can understand.
231262

232263
# Find Jansson
233264
jansson_flags = subprocess.check_output(['pkg-config', '--cflags', 'jansson']).decode('utf-8').strip().split(' ')

0 commit comments

Comments
 (0)