Skip to content

Embed nrnunits.lib #3471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions cmake/ConfigFileSetting.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,17 @@ configure_file("${PROJECT_SOURCE_DIR}/src/sundials/sundials_config.h.in"
"${PROJECT_BINARY_DIR}/src/sundials/sundials_config.h" @ONLY)
configure_file("${PROJECT_SOURCE_DIR}/share/lib/nrn.defaults.in"
"${PROJECT_BINARY_DIR}/share/nrn/lib/nrn.defaults" @ONLY)
file(COPY ${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib
DESTINATION ${PROJECT_BINARY_DIR}/share/nrn/lib)
set(nrnunits_start "")
set(nrnunits_stop "")

configure_file(${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib.in
${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib @ONLY)

set(nrnunits_start "R\"qwerty(")
Copy link
Member

@nrnhines nrnhines Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional...Could use a comment. Took me a while (and looking at the constructed embedded_nrnunit.lib file) to realize the reason for the start/stop idiom. I'd never seen this C++ feature before

set(nrnunits_stop ")qwerty\"")
# Embed nrnunits
configure_file(${PROJECT_SOURCE_DIR}/share/lib/nrnunits.lib.in
${PROJECT_BINARY_DIR}/share/nrn/lib/embedded_nrnunits.lib @ONLY)

if(NRN_MACOS_BUILD)
set(abs_top_builddir ${PROJECT_BINARY_DIR})
Expand Down
4 changes: 2 additions & 2 deletions share/lib/nrnunits.lib → share/lib/nrnunits.lib.in
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was renamed because we use cpp_cc_build_time_copy on some of the directories, so nrnunits.lib was first set-up at configure time, but then cpp_cc_build_time_copy would clobber it at build-time, so to work around it, we just rename it.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/ from gnu units distribution
@nrnunits_start@/ from gnu units distribution
/ Nov, 2017 updated faraday, R, e, planck, hbar, mole, k according to
/ https://physics.nist.gov/cuu/Constants/index.html

Expand Down Expand Up @@ -617,4 +617,4 @@ metricyarncount meter/gram
jewlerspoint 2 milligram



@nrnunits_stop@
24 changes: 24 additions & 0 deletions src/modlunit/units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <algorithm>
#include <string>
#include <string_view>
#include <fstream>

/* /local/src/master/nrn/src/modlunit/units.c,v 1.5 1997/11/24 16:19:13 hines Exp */
/* Mostly from Berkeley */
Expand Down Expand Up @@ -100,6 +102,23 @@ static int dumpflg;

static const char* pc;

static constexpr std::string_view embedded_nrnunits =
#include "embedded_nrnunits.lib"
;

// cross-platform workaround for:
// https://github.com/neuronsimulator/nrn/issues/3470
// the API requires a FILE handle instead of a std::string or similar
// so we write a temporary file
static FILE* open_embedded_nrnunits_as_file() {
auto tmp_path = std::string(std::tmpnam(nullptr));
auto out = std::ofstream(tmp_path, std::ios::out);
out.write(embedded_nrnunits.data(), embedded_nrnunits.size());
out.close();

return std::fopen(tmp_path.c_str(), "r");
}

static int Getc(FILE* inp) {
if (inp != stdin) {
return getc(inp);
Expand Down Expand Up @@ -565,6 +584,11 @@ void unit_init() {
}
#endif

// try to load the embedded one as a last resort
if (!inpfile) {
inpfile = open_embedded_nrnunits_as_file();
}

if (!inpfile) {
fprintf(stderr, "Set a MODLUNIT environment variable path to the units table file\n");
fprintf(stderr, "Cant open units table in either of:\n%s\n", buf);
Expand Down
2 changes: 2 additions & 0 deletions src/nrniv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ add_dependencies(generated_source_files modlunit_generated_files)
add_executable(modlunit ${NRN_MODLUNIT_SRC_FILES} "${NRN_MODLUNIT_GEN}/lex.cpp"
"${NRN_MODLUNIT_GEN}/parse1.cpp")
add_dependencies(modlunit modlunit_generated_files)
target_include_directories(modlunit PRIVATE "${PROJECT_BINARY_DIR}/share/nrn/lib")

target_compile_definitions(modlunit PRIVATE NRNUNIT=1)
cpp_cc_configure_sanitizers(TARGET modlunit)
Expand Down Expand Up @@ -96,6 +97,7 @@ add_dependencies(generated_source_files nocmodl_generated_files)

add_executable(nocmodl ${NRN_NOCMODL_SRC_FILES} "${NRN_NOCMODL_GEN}/lex.cpp"
"${NRN_NOCMODL_GEN}/parse1.cpp" "${NRN_NOCMODL_GEN}/diffeq.cpp")
target_include_directories(nocmodl PRIVATE "${PROJECT_BINARY_DIR}/share/nrn/lib")
cpp_cc_configure_sanitizers(TARGET nocmodl)
add_dependencies(nocmodl nocmodl_generated_files)
target_compile_definitions(nocmodl PRIVATE COMPILE_DEFINITIONS NMODL=1 CVODE=1)
Expand Down
8 changes: 7 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -802,8 +802,14 @@ add_modlunit_test("${PROJECT_SOURCE_DIR}/src/nrnoc/hh.mod")
add_modlunit_test("${PROJECT_SOURCE_DIR}/src/nrnoc/stim.mod")
add_modlunit_test("${PROJECT_SOURCE_DIR}/src/nrnoc/pattern.mod")
add_modlunit_test("${PROJECT_SOURCE_DIR}/test/hoctests/rand.mod")
# Test nocmodl with units
add_test(
NAME nocmodl::no_env
COMMAND $<TARGET_FILE:nocmodl> -o "${CMAKE_CURRENT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/test/coreneuron/mod files/axial.mod"
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
set_property(TEST modlunit_pattern PROPERTY WILL_FAIL ON)

cpp_cc_configure_sanitizers(TEST nocmodl::no_env)
set_tests_properties(${TESTS} PROPERTIES ENVIRONMENT "${NRN_RUN_FROM_BUILD_DIR_ENV}")
cpp_cc_configure_sanitizers(TEST ${TESTS})
# If profiling is enabled, run ringtest with profiler
Expand Down
Loading