Skip to content

Commit 3b7cad7

Browse files
pramodknrnhines
authored andcommitted
[WIP] CMake build system refactoring (#247)
* Started top level refactoring * Top level CMake 2 * Top level CMake refactor part 3 * Top level refactoring 4 * Top level refactoring 5 * Add build status after cmake stage * CMake modules refactoring * Avoid python2 library detection when default python is 3 I was getting: -- Python | 1 -- EXE | /usr/local/Cellar/python/3.7.2_2/bin/python -- LIB | /usr/lib/libpython2.7.dylib Prefer version detected as interpreter * Bug fix for python library detection, use pybind11 module which has worked very well. See: pybind/pybind11#207 * WIP Refactoring : cmake_config/CMakeLists.txt * Refactoring of cmake_config/CMakeLists.txt part 2 * Big refactoring of src/nrniv/CMakeLists.txt * Refactoring of src/nrnpython/CMakeLists.txt * Bug fixes for ubuntu
1 parent 5128ba8 commit 3b7cad7

22 files changed

+1862
-1096
lines changed

CMakeLists.txt

Lines changed: 138 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,86 @@
11
cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR)
2-
project(nrn C CXX)
2+
project(NEURON C CXX)
33

44
# =============================================================================
55
# CMake common project settings
66
# =============================================================================
77
set(PROJECT_VERSION_MAJOR 7)
88
set(PROJECT_VERSION_MINOR 7)
9-
set(CMAKE_BUILD_TYPE Debug)
109
set(CMAKE_CXX_STANDARD 98)
1110
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1211
set(CMAKE_CXX_EXTENSIONS OFF)
12+
set(CMAKE_BUILD_TYPE RelWithDebInfo)
1313
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
14+
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
1415

15-
# needed in several subdirectoy configurations
16-
set (prefix ${CMAKE_INSTALL_PREFIX})
17-
set (host_cpu ${CMAKE_SYSTEM_PROCESSOR})
18-
set (exec_prefix ${prefix})
19-
set (bindir \${exec_prefix}/bin)
20-
set (libdir \${exec_prefix}/lib)
21-
set (PACKAGE "\"nrn\"")
22-
23-
option(NRN_BUILD_SHARED "Build libraries shared or static" ON)
24-
option(ENABLE_INTERVIEWS "Link with INTERVIEWS GUI library" ON)
25-
option(ENABLE_LegacyFR "Original faraday, R, etc. instead of 2017 nist constants in share/lib/nrnunits.lib" ON)
26-
option(ENABLE_NRNMECH_DLL_STYLE "Dynamically load nrnmech shared library" ON)
27-
option(ENABLE_DISCRETE_EVENT_OBSERVER "Set to OFF if do not want Observer to be a subclass of DiscreteEvent" ON)
28-
option(ENABLE_PYTHON "Python interpreter available -- python3 fallback to python" ON)
29-
option(ENABLE_THREADS "Allow use of pthreads" ON)
30-
option(ENABLE_MPI "Allow use of MPI" ON)
31-
option(ENABLE_MEMACS "Allow use of memacs" ON)
32-
option(ENABLE_RX3D "Allow use of rx3d" OFF)
33-
34-
set(INSTALL_NEURON_MODULE "YES" CACHE STRING "\"NO\", means do not \
35-
install the neuron module. \"Yes\", means to install with --home in \
36-
CMAKE_INSTALL_PREFIX. For installation using other modes or locations \
37-
use an appropriate string that goes after python setup.py install")
38-
39-
set(NRNPYTHON_DYNAMIC "NO" CACHE STRING "\"NO\", means the nrnpython
40-
interface is linked into libnrniv.so. \"YES\" means the nrnpython
41-
interface consistent with default python3 (falling back to python) is
42-
built and loaded dynamically at run time (nrniv still works in the
43-
absence of any Python at all). A ';' separated list of executable
44-
pythons are used to create a separate interface for each. When one of
45-
those versions of Python is lauched,
46-
import neuron
47-
will automatically load the appropriate module interface along with the
48-
rest of neuron. (And
49-
nrniv -pyexe <python>
50-
will work with any <python> in the list of python executables.")
16+
# =============================================================================
17+
# Build options (boolean)
18+
# =============================================================================
19+
option(NRN_BUILD_SHARED "Build shared libraries (otherwise static library)" ON)
20+
option(NRN_ENABLE_INTERVIEWS "Enable GUI with INTERVIEWS" ON)
21+
option(NRN_ENABLE_LEGACY_FR "Use original faraday, R, etc. instead of 2017 nist constants" ON)
22+
option(NRN_ENABLE_MECH_DLL_STYLE "Dynamically load nrnmech shared library" ON)
23+
option(NRN_ENABLE_DISCRETE_EVENT_OBSERVER "Enable Observer to be a subclass of DiscreteEvent" ON)
24+
option(NRN_ENABLE_PYTHON "Enable Python interpreter support (default python3 fallback to python)" ON)
25+
option(NRN_ENABLE_THREADS "Allow use of Pthreads" ON)
26+
option(NRN_ENABLE_MPI "Enable MPI support" ON)
27+
option(NRN_ENABLE_MEMACS "Enable use of memacs" ON)
28+
option(NRN_ENABLE_RX3D "Enable rx3d support" OFF)
5129

52-
set(NRNMPI_DYNAMIC "NO" CACHE STRING "\"No\", means the nrnmpi
53-
is linked into libnrniv.so. \"YES\", means the nrnmpi interface
54-
consistent with default mpi is built and loaded dynamically at run
55-
time (nrniv still works in the absence of any mpi at all). A ';'
56-
separated list of paths to mpi package bin directories is used to
57-
create a separate libnrnmpi_xxx.so interface for each. When nrniv
58-
is launched with the -mpi argument, the first mpi found will determine
59-
which interface is dynamically loaded.")
30+
# =============================================================================
31+
# Build options (string)
32+
# =============================================================================
6033

61-
set(USING_CMAKE_FALSE "#")
62-
set(USING_CMAKE_TRUE "")
34+
# NEURON module installation:
35+
# - NO : do not install
36+
# - YES : install with --home in ${CMAKE_INSTALL_PREFIX}
37+
# - <string> : install using other modes or locations using an appropriate
38+
# string that goes after python setup.py install
39+
# Dynamic Python version support:
40+
# - NO : nrnpython interface is linked into libnrniv.so
41+
# - YES : nrnpython interface consistent with default python3 (falling back to python)
42+
# is built and loaded dynamically at run time (nrniv still works in the absence
43+
# of any Python at all).
44+
# - <string> : semicolon (;) separated list of python executable used to create a separate
45+
# interface for each. When one of those versions of Python is lauched,
46+
# "import neuron" will automatically load the appropriate module interface along
47+
# with the rest of neuron. Alsom nrniv -pyexe <python> will work with any <python>
48+
# in the list of python executables.
49+
# Dynamic MPI support:
50+
# - NO : nrnmpi is linked into libnrniv.so
51+
# - YES : nrnmpi interface is consistent with default mpi is built and loaded dynamically
52+
# at run time (nrniv still works in the absence of any mpi at all).
53+
# - <string> : semicolon (;) separated list of MPI's bin directories to create a separate
54+
# libnrnmpi_xxx.so interface for each. When nrniv is launched with the -mpi argument,
55+
# the first mpi found will determine which interface is dynamically loaded."
56+
set(NRN_ENABLE_MODULE_INSTALL YES CACHE STRING "Enable NEURON module installation (with setup.py)")
57+
set(NRN_ENABLE_PYTHON_DYNAMIC "NO" CACHE STRING "Enable dynamic Python version support")
58+
set(NRN_ENABLE_MPI_DYNAMIC "NO" CACHE STRING "Enable dynamic MPI library support")
6359

6460
# =============================================================================
65-
# Compile static libraries with hidden visibility
61+
# Include cmake modules
6662
# =============================================================================
67-
#set(CMAKE_CXX_VISIBILITY_PRESET hidden)
63+
list(APPEND CMAKE_MODULE_PATH
64+
${PROJECT_SOURCE_DIR}/cmake
65+
${PROJECT_SOURCE_DIR}/cmake/modules)
66+
include(CompilerHelper)
67+
include(MacroHelper)
68+
include(RpathHelper)
69+
include(PlatformHelper)
6870

6971
# =============================================================================
7072
# Find required packages
7173
# =============================================================================
72-
message(STATUS "CHECKING FOR X11")
7374
find_package(BISON)
7475
find_package(FLEX)
76+
find_package(readline)
7577

76-
if (ENABLE_MPI)
78+
# =============================================================================
79+
# Enable MPI/Python/IV/Pthead if found
80+
# =============================================================================
81+
# enable mpi if found
82+
if (NRN_ENABLE_MPI)
7783
find_package(MPI REQUIRED)
78-
# TODO : include this for only selective target
7984
include_directories(${MPI_INCLUDE_PATH})
8085
set(NRNMPI 1)
8186
set(PARANEURON 1)
@@ -84,36 +89,34 @@ else()
8489
set(PARANEURON 0)
8590
endif()
8691

87-
if (ENABLE_INTERVIEWS)
92+
# enable interviews if found
93+
if (NRN_ENABLE_INTERVIEWS)
8894
find_package(X11)
8995
if(NOT ${X11_FOUND})
9096
if (APPLE)
9197
message(FATAL_ERROR "You must install XQuartz from https://www.xquartz.org/ to build iv")
9298
else()
93-
find_package(X11 REQUIRED)
99+
message(FATAL_ERROR "You must install X11 to build iv e.g. 'apt install libx11-dev libxcomposite-dev' on Ubuntu")
94100
endif()
95101
endif()
96-
include_directories(${X11_INCLUDE_DIR})
97102
find_package(iv REQUIRED)
103+
include_directories(${X11_INCLUDE_DIR})
98104
set (HAVE_IV 1)
99105
else()
100-
set (HAVE_IV 0)
106+
set(HAVE_IV 0)
101107
endif()
102108

103-
# python or python3 is also needed to make hocusr.h from neuron.h
104-
set(Python_ADDITIONAL_VERSIONS 3.6) # 3.x priority, then 2.x
105-
find_package(PythonInterp REQUIRED) #currently active
106-
message(NOTICE "ENABLE_PYTHON ${ENABLE_PYTHON}")
107-
if (ENABLE_PYTHON)
108-
message(NOTICE " inside ENABLE_PYTHON")
109-
find_package(PythonLibs REQUIRED) # consistent with above
109+
# enable python support (interpreter needed to make hocusr.h from neuron.h, prefer Python 3)
110+
find_package(PythonInterp REQUIRED)
111+
if (NRN_ENABLE_PYTHON)
112+
find_package(PythonLibsNew ${PYTHON_VERSION_MAJOR} REQUIRED)
110113
set(USE_PYTHON 1)
111-
message(NOTICE "USE_PYTHON ${USE_PYTHON}")
112114
else()
113115
set(USE_PYTHON 0)
114116
endif()
115117

116-
if (ENABLE_THREADS)
118+
# enable threads if found
119+
if (NRN_ENABLE_THREADS)
117120
set(THREADS_PREFER_PTHREAD_FLAG ON)
118121
find_package(Threads REQUIRED)
119122
set(USE_PTHREAD 1)
@@ -122,70 +125,89 @@ else()
122125
endif()
123126

124127
# =============================================================================
125-
# Include cmake modules
128+
# Add CMake modules AFTER setting options
126129
# =============================================================================
127-
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
128-
include(RpathHelper)
129-
include(ConfigACFile)
130-
include(NrnPyDynamic)
131-
include(NrnMPIDynamic)
130+
include(ConfigFileSetting)
131+
include(NeuronFileLists)
132+
include(PythonDynamicHelper)
133+
include(MPIDynamicHelper)
132134

133135
# =============================================================================
134136
# Project version from git and project directories
135137
# =============================================================================
136-
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
137-
138-
add_definitions(-DHAVE_CONFIG_H)
139-
140-
if(${CMAKE_SYSTEM_NAME} MATCHES "CYGWIN")
141-
set(CYGWIN 1)
138+
add_subdirectory(cmake_config)
139+
add_subdirectory(src/nrniv)
140+
add_subdirectory(bin)
141+
if (NRN_ENABLE_PYTHON)
142+
add_subdirectory(src/nrnpython)
143+
endif()
144+
if (NRN_MACOS_BUILD OR NOT ${READLINE_FOUND})
145+
add_subdirectory(src/readline)
146+
set(INTERNAL_READLINE readline)
147+
unset(Readline_LIBRARY CACHE)
142148
endif()
143149

144-
add_subdirectory(cmkconfig)
150+
# =============================================================================
151+
# Install targets
152+
# =============================================================================
153+
# find headers to install
154+
nrn_find_project_files(NRN_HEADERS_PATHS ${HEADER_FILES_TO_INSTALL})
145155

146-
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/lib
147-
DESTINATION share/nrn)
148-
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/demo
149-
DESTINATION share/nrn)
150-
install(FILES ${PROJECT_BINARY_DIR}/share/lib/nrnunits.lib
156+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/lib DESTINATION share/nrn)
157+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/demo DESTINATION share/nrn)
158+
install(FILES
159+
${PROJECT_BINARY_DIR}/share/lib/nrnunits.lib
151160
${PROJECT_BINARY_DIR}/share/lib/nrn.defaults
152161
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/nrn/lib
153162
)
154-
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/share/lib/cleanup
163+
install(PROGRAMS
164+
${CMAKE_CURRENT_SOURCE_DIR}/share/lib/cleanup
155165
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/nrn/lib
156166
)
157-
158-
# paths to *.h files for installing into <prefix>/include
159-
my_find_files(inst_inc
160-
cabvars.h hoc_membf.h neuron.h nrnjava.h options.h
161-
cspmatrix.h hocparse.h nmodlmutex.h nrnoc_ml.h scoplib_ansi.h
162-
cspredef.h md1redef.h nrn_ansi.h scoplib.h
163-
hocassrt.h md2redef.h nrnapi.h nrnran123.h section.h
164-
hocdec.h membdef.h nrnassrt.h nrnredef.h spconfig.h
165-
hocgetsym.h membfunc.h nrncvode.h oc_ansi.h spmatrix.h
166-
hoc.h multicore.h nrnisaac.h ocfunc.h
167-
hoclist.h multisplit.h nrniv_mf.h ocmisc.h
168-
)
169-
install(FILES ${inst_inc} ${PROJECT_BINARY_DIR}/src/oc/nrnpthread.h
167+
install(FILES
168+
${NRN_HEADERS_PATHS} ${PROJECT_BINARY_DIR}/src/oc/nrnpthread.h
170169
DESTINATION ${CMAKE_INSTALL_PREFIX}/include
171170
)
172171

173-
find_package(readline)
174-
175-
# if readline not found or if we are on OSX, use internal readline
176-
# also clear library variable
177-
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR NOT ${READLINE_FOUND})
178-
add_subdirectory(src/readline)
179-
set(INTERNAL_READLINE readline)
180-
unset(Readline_LIBRARY CACHE)
181-
endif()
182-
183-
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
184-
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS} -undefined dynamic_lookup")
185-
endif()
186-
187-
add_subdirectory(src/nrniv)
188-
add_subdirectory(bin)
189-
if (ENABLE_PYTHON)
190-
add_subdirectory(src/nrnpython)
172+
# =============================================================================
173+
# Print build status
174+
# =============================================================================
175+
message(STATUS "")
176+
message(STATUS "Configured NEURON ${PROJECT_VERSION}")
177+
message(STATUS "")
178+
string(TOLOWER "${CMAKE_GENERATOR}" cmake_generator_tolower)
179+
if(cmake_generator_tolower MATCHES "makefile")
180+
message(STATUS "Some things you can do now:")
181+
message(STATUS "--------------+--------------------------------------------------------------")
182+
message(STATUS "Command | Description")
183+
message(STATUS "--------------+--------------------------------------------------------------")
184+
message(STATUS "make install | Will install NEURON to: ${CMAKE_INSTALL_PREFIX}")
185+
message(STATUS " | Change the install location of NEURON using:")
186+
message(STATUS " | cmake <src_path> -DCMAKE_INSTALL_PREFIX=<install_path>")
187+
message(STATUS "make doc | Build the API documentation, requires Sphinx")
188+
message(STATUS "make uninstall| Removes files installed by make install")
189+
message(STATUS "--------------+--------------------------------------------------------------")
190+
message(STATUS " Build option | Status")
191+
message(STATUS "--------------+--------------------------------------------------------------")
192+
message(STATUS "Interviews | ${HAVE_IV}")
193+
message(STATUS "MPI | ${NRNMPI}")
194+
if(NRN_ENABLE_MPI)
195+
message(STATUS " INC | ${MPI_INCLUDE_PATH}")
196+
message(STATUS " LIB | ${MPI_LIBRARY}")
197+
endif()
198+
message(STATUS "Python | ${USE_PYTHON}")
199+
if(NRN_ENABLE_PYTHON)
200+
message(STATUS " EXE | ${PYTHON_EXECUTABLE}")
201+
message(STATUS " LIB | ${PYTHON_LIBRARY}")
202+
if (NOT NRN_ENABLE_PYTHON_DYNAMIC MATCHES "NO")
203+
message(STATUS " INC(2) | ${NRNPYTHON_INCLUDE2}")
204+
message(STATUS " INC(3) | ${NRNPYTHON_INCLUDE3}")
205+
endif()
206+
endif()
207+
message(STATUS "RXD | ${NRN_ENABLE_RX3D}")
208+
message(STATUS "Shared | ${NRN_BUILD_SHARED}")
209+
message(STATUS "--------------+--------------------------------------------------------------")
210+
message(STATUS " See documentation : https://www.neuron.yale.edu/neuron/")
211+
message(STATUS "--------------+--------------------------------------------------------------")
191212
endif()
213+
message(STATUS "")

bin/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsNrnMech.txt)
2828

2929
set(NRNMECH_DLL_STYLE_FALSE "\#")
3030
set(NRNMECH_DLL_STYLE_TRUE "")
31-
configure_ac_file(nrngui bin)
32-
configure_ac_file(neurondemo bin)
33-
configure_ac_file(nrnivmodl bin)
31+
nrn_configure_file(nrngui bin)
32+
nrn_configure_file(neurondemo bin)
33+
nrn_configure_file(nrnivmodl bin)
3434
#nrnmech_makefile.in is intimately bound up with autoconf (libtool)
35-
#configure_ac_file(nrnmech_makefile bin)
35+
#nrn_configure_file(nrnmech_makefile bin)
3636
#so instead use a modified copy of the CoreNEURON version of
3737
#nrnivmodl_core_makefile.in
3838
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nrnivmodl_makefile.cmk

bin/CMakeListsNrnMech.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ endif()
4343
string(TOUPPER "${CMAKE_BUILD_TYPE}" _BUILD_TYPE)
4444
set(BUILD_TYPE_C_FLAGS "${CMAKE_C_FLAGS_${_BUILD_TYPE}}")
4545
set(BUILD_TYPE_CXX_FLAGS "${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}")
46-
message("CXX Compile Flags from BUILD_TYPE: ${BUILD_TYPE_CXX_FLAGS}")
46+
message(STATUS "CXX Compile Flags from BUILD_TYPE: ${BUILD_TYPE_CXX_FLAGS}")
4747

4848
if (FALSE) # done in top level CMakeLists.txt
4949
configure_file(${nmodl_makefile}.in ${nmodl_makefile} @ONLY)

bin/nrndiagnose.sh.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ PYTHONBLD="@PYTHON_BLD@" # The python used for
2323
PYTHONCFG="@PYTHON@" # The Python from --with_nrnpython or --pyexe
2424
host_cpu="@host_cpu@"
2525
host_os="@host_os@"
26-
NRNPYTHON_DYNAMIC=no
26+
NRN_ENABLE_PYTHON_DYNAMIC=no
2727
nrnPYTHONPATH="$prefix/lib/python"
2828

2929
diagnose() {
@@ -40,7 +40,7 @@ diagnose() {
4040
echo "PYTHON=$PYTHON"
4141
echo "host_cpu=$host_cpu"
4242
echo "host_os=$host_os"
43-
echo "NRNPYTHON_DYNAMIC=$NRNPYTHON_DYNAMIC"
43+
echo "NRN_ENABLE_PYTHON_DYNAMIC=$NRN_ENABLE_PYTHON_DYNAMIC"
4444
echo "origPYTHONPATH=$origPYTHONPATH"
4545
echo "origPYTHONHOME=$origPYTHONHOME"
4646
echo "origNRN_PYLIB=$origNRN_PYLIB"
@@ -95,7 +95,7 @@ unset PYTHONPATH # pristine, just going to check for runability
9595

9696
PYTHON=""
9797
if test "@BUILD_NRNPYTHON_DYNAMIC_FALSE@" = "#" ; then
98-
NRNPYTHON_DYNAMIC=yes
98+
NRN_ENABLE_PYTHON_DYNAMIC=yes
9999
if $PYTHONCFG -c 'quit()' > /dev/null 2>& 1 ; then
100100
PYTHON="$PYTHONCFG" #last one built
101101
else # python for last one built is not on this machine

cmake/CompilerHelper.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# =============================================================================
2+
# Compiler specific settings
3+
# =============================================================================
4+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5+
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS} -undefined dynamic_lookup")
6+
endif()

0 commit comments

Comments
 (0)