diff --git a/.github/workflows/build_and_run_unit_test.yml b/.github/workflows/build_and_run_unit_test.yml index 5915151..e1627d2 100644 --- a/.github/workflows/build_and_run_unit_test.yml +++ b/.github/workflows/build_and_run_unit_test.yml @@ -34,15 +34,15 @@ jobs: - name: Build and Run Unit Test run: | - cd ./test - make clean - make 'CFLAGS=-g -Og -fsanitize=address -Werror' - ./run_bmi_unit_test - - - name: Build and Run Standalone + cmake -B cmake_build -DCMAKE_C_FLAGS="-g -Og -fsanitize=address -Werror" -S . + cmake --build cmake_build --target clean + cmake --build cmake_build --target simple_unit_tests + cd cmake_build/ + ./simple_unit_tests + + - name: Build and Run Standalone run: | - cd src/ - make clean - make 'CFLAGS=-g -Og -fsanitize=address -Werror' - cd .. - ./run_bmi + cmake -B cmake_build -DCMAKE_C_FLAGS="-g -Og -fsanitize=address -Werror" -S . + cmake --build cmake_build --target clean + cmake --build cmake_build --target topmodeldriver + ./cmake_build/topmodeldriver diff --git a/.github/workflows/ngen_integration.yaml b/.github/workflows/ngen_integration.yaml index 96b4833..cbb0c7d 100644 --- a/.github/workflows/ngen_integration.yaml +++ b/.github/workflows/ngen_integration.yaml @@ -101,20 +101,14 @@ jobs: bmi_fortran: 'ON' timeout-minutes: 15 + # For the time being, generate a CMake build directory aligned as if this was a submodule (i.e., under extern/) + # However, don't use the code or CMakeLists.txt there (and don't use ngen-submod-build) - name: Prepare to Build Topmodel Library for Ngen - run: | - # Move files to appropriate directory to build topmodel library - rm -rf extern/topmodel/topmodel/* - mv ${{runner.temp}}/topmodel/* extern/topmodel/topmodel + run: cmake -B extern/topmodel/cmake_build -DCMAKE_C_FLAGS="-g -Og -fsanitize=address -Werror" -S ${{runner.temp}}/topmodel/ - name: Build Topmodel id: submod_build_4 - uses: ./.github/actions/ngen-submod-build - with: - mod-dir: " extern/topmodel/" - targets: "topmodelbmi" - initialize: "false" - cmake-flags: "-DCMAKE_C_FLAGS='-g -Og -fsanitize=address -Werror'" + run: cmake --build extern/topmodel/cmake_build --target topmodelbmi - name: Run petbmi, topmodelbmi run: | diff --git a/.gitignore b/.gitignore index cd5ee98..ec20a1a 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,4 @@ params/data/TopModel_Results/ # Misc # ######## make_and_run_bmi.sh +.idea diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c08200e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.17) + +option(TESTS_WITH_ASAN "Enable AddressSanitizer on the test targets" ON) + +project(topmodelbmi VERSION 1.0.0 DESCRIPTION "OWP TOPMODEL Model and BMI Module Shared Library") + +set(TOPMODEL_LIB_NAME_CMAKE topmodelbmi) +set(TOPMODEL_LIB_DESC_CMAKE "OWP TOPMODEL Model and BMI Module Shared Library") + +#################### +# Some global properties +set_property(GLOBAL PROPERTY C_STANDARD 99) # Note that code requires minimum of C99 standard to compile +set_property(GLOBAL PROPERTY C_STANDARD_REQUIRED ON) +#################### + +#################### +# Stuff for shared library +if(WIN32) + add_library(topmodelbmi src/bmi_topmodel.c src/topmodel.c) +else() + add_library(topmodelbmi SHARED src/bmi_topmodel.c src/topmodel.c) +endif() + +target_compile_definitions(topmodelbmi PRIVATE BMI_ACTIVE) +target_include_directories(topmodelbmi PRIVATE include) +target_link_libraries(topmodelbmi m) +set_target_properties(topmodelbmi PROPERTIES + VERSION ${PROJECT_VERSION} + PUBLIC_HEADER include/bmi_topmodel.h +) +#################### + +#################### +# Stuff for standalone driver executable +add_executable(topmodeldriver src/main.c src/bmi_topmodel.c src/topmodel.c) +target_include_directories(topmodeldriver PRIVATE include) +target_link_libraries(topmodeldriver m) +#################### + +#################### +# Stuff for simple test routine +add_executable(simple_unit_tests test/main_unit_test_bmi.c src/bmi_topmodel.c src/topmodel.c) +target_compile_definitions(simple_unit_tests PRIVATE REPO_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(simple_unit_tests PRIVATE include) +target_link_libraries(simple_unit_tests m) +if (TESTS_WITH_ASAN) + # Seems this should work in all compiler + target_compile_options(simple_unit_tests PRIVATE -fsanitize=address) + target_link_options(simple_unit_tests PRIVATE -fsanitize=address) +endif () +#################### + +include(GNUInstallDirs) + +install(TARGETS topmodelbmi + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) \ No newline at end of file diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 4d1dc17..0000000 --- a/src/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# define the C compiler to use -CC = gcc - -# define any compile-time flags -# for newer compiler, the right hand side is not needed -CFLAGS = -std=c99 - -INCLUDES = -I../include - -LFLAGS = - -LIBS = -lm - -# define the C source files -SRCS = main.c bmi_topmodel.c topmodel.c - -# define the C object files -OBJS = $(SRCS:.c=.o) - -# define the executable file -MAIN = run_bmi - -.PHONY: depend clean - -all: $(MAIN) - @echo Simple compiler named mycc has been compiled - @mv run_bmi .. - -$(MAIN): $(OBJS) - $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS) - -# this is a suffix replacement rule for building .o's from .c's -# it uses automatic variables $<: the name of the prerequisite of -# the rule(a .c file) and $@: the name of the target of the rule (a .o file) -# (see the gnu make manual section about automatic variables) -.c.o: - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -clean: - $(RM) *.o *~ $(MAIN) - -depend: $(SRCS) - makedepend $(INCLUDES) $^ diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index c99a47e..0000000 --- a/test/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# define the C compiler to use -CC = gcc -g - -# define any compile-time flags -# for newer compiler, the right hand side is not needed... -# ... for instance, remove the flags if using gnu/10.1.0 on Cheyenne. -CFLAGS = -fsanitize=address - -INCLUDES = -I../include - -LFLAGS = - -LIBS = -lm - -# define the C source files -SRCS = main_unit_test_bmi.c ../src/bmi_topmodel.c ../src/topmodel.c - -# define the C object files -OBJS = $(SRCS:.c=.o) - -# define the executable file -MAIN = run_bmi_unit_test - -.PHONY: depend clean - -all: $(MAIN) - @echo Simple compiler named mycc has been compile - -$(MAIN): $(OBJS) - $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS) - -# this is a suffix replacement rule for building .o's from .c's -# it uses automatic variables $<: the name of the prerequisite of -# the rule(a .c file) and $@: the name of the target of the rule (a .o file) -# (see the gnu make manual section about automatic variables) -.c.o: - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -clean: - $(RM) *.o *~ $(MAIN) - -depend: $(SRCS) - makedepend $(INCLUDES) $^ diff --git a/test/data/topmod_unit_test.run b/test/data/topmod_unit_test.run index a128311..d6c6695 100644 --- a/test/data/topmod_unit_test.run +++ b/test/data/topmod_unit_test.run @@ -1,7 +1,7 @@ 0 Taegu Pyungkwang River Catchment: Calibration Data -data/inputs.dat -data/subcat.dat -data/params.dat +../test/data/inputs.dat +../test/data/subcat.dat +../test/data/params.dat topmod.out hyd.out \ No newline at end of file diff --git a/test/main_unit_test_bmi.c b/test/main_unit_test_bmi.c index 356afd2..eb6fcd3 100755 --- a/test/main_unit_test_bmi.c +++ b/test/main_unit_test_bmi.c @@ -24,7 +24,14 @@ main(void){ // Test BMI: CONTROL FUNCTION initialize() { printf(" initializing..."); - const char *cfg_file = "./data/topmod_unit_test.run"; + + #ifndef REPO_ROOT_DIR + // We need this next for a const string, so bail if it hasn't been defined + printf("Please set REPO_ROOT_DIR build macro and rebuild test executable"); + return BMI_FAILURE; + #endif + + const char *cfg_file = REPO_ROOT_DIR "/test/data/topmod_unit_test.run"; printf(" configuration found: %s\n", cfg_file); status = model->initialize(model, cfg_file); if (status == BMI_FAILURE) return BMI_FAILURE;