How to organize my directories, subdirectories, files and CMakeLists.txt for CMake?

Viewed 72

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
0 Answers
Related