I want to compile a program using CMake in Project/build/ directory having a following organization:
---Project/
---CMakeLists.txt
---main/
---main.f90
---library/
---CMakeLists.txt
---call_ts_module.f90
---call_ts.cpp
---call_ts.h
---torchscript.pt
---libtorch/
---<libtorch libraries>
---build/
The main Fortran program Project/main/main.f90 calls call_ts_subroutine defined in module Project/library/call_ts_module.f90, which calls a c++ function invariant_nn defined in Project/library/call_ts.cpp and Project/library/call_ts.h, which invoke a torchscript Project/library/torchscript.pt.
How should Project/CMakeLists.txt and Project/library/CMakeLists.txt look like? I tried following ones (I am totally new to CMake), but they did not work (make does not see the header file call_ts_export.h):
Project/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(fortran_calls_ts CXX Fortran)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
set(CMAKE_Fortran_FLAGS_RELEASE "-O3")
find_package(Torch REQUIRED)
add_subdirectory(library)
add_executable(fortran_calls_ts.x main/main.f90)
target_link_libraries(fortran_calls_ts.x library)
set_property(TARGET fortran_calls_ts.x PROPERTY CXX_STANDARD 14)
Project/library/CMakeLists.txt:
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
add_library(library SHARED call_ts_module.f90)
add_library(call_ts_cpp SHARED call_ts.cpp)
target_link_libraries(library call_ts_cpp)
target_link_libraries(call_ts_cpp "${TORCH_LIBRARIES}")
include(GenerateExportHeader)
generate_export_header(call_ts_cpp BASE_NAME call_ts)
install(TARGETS call_ts_cpp LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
install(FILES call_ts.h ${PROJECT_BINARY_DIR}/call_ts_export.h DESTINATION include)
Project/main/main.f90
program main
use call_ts_module
...
call call_ts_subroutine()
...
end program main
Project/library/call_ts_module.f90
module call_ts_module
contains
subroutine call_ts_subroutine()
use, intrinsic :: iso_c_binding, only: c_float
implicit none
interface invariant_nn
subroutine invariant_nn(I, G) bind (c)
import :: c_float
real(c_float) :: I(5)
real(c_float) :: G(10)
end subroutine
end interface
real(4) I(5), G(10)
...
call invariant_nn(I, G)
...
end subroutine call_ts_subroutine
end module call_ts_module
Project/library/call_ts.cpp
#include "call_ts.h"
#include <torch/script.h>
#include <iostream>
#include <memory>
void invariant_nn(float I[], float G[])
{
torch::jit::script::Module module;
const char *arg;
arg = "../library/torchscript.pt";
module = torch::jit::load(arg);
std::vector<torch::jit::IValue> inputs;
float data[] = {I[0], I[1], I[2], I[3], I[4]};
inputs.push_back(torch::from_blob(data, {1, 5}));
at::Tensor outputs = module.forward(inputs).toTensor();
for (int k = 0; k < 10; k++) {
G[k] = outputs[0][k].item().to<float>();
}
return;
}
Project/library/call_ts.h
#pragma once
#ifndef CALL_TS_API
#include "call_ts_export.h"
#define CALL_TS_API CALL_TS_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
CALL_TS_API
void invariant_nn(float I[], float G[]);
#ifdef __cplusplus
}
#endif