Skip to content
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

omp module logic troubled by newer cmake #247

Open
loriab opened this issue May 11, 2018 · 26 comments
Open

omp module logic troubled by newer cmake #247

loriab opened this issue May 11, 2018 · 26 comments
Assignees

Comments

@loriab
Copy link

loriab commented May 11, 2018

I don't think the autocmake OpenMP module is playing nicely with modern Kitware OpenMP module.

In particular, when C/CXX/Fortran are active languages, if FindOpenMP finds flags & libs for C & CXX but not for Fortran, then OPENMP_FOUND is False, so no flags get added to CMAKE__FLAGS in this section. But then Fortran does pick up flags in this section b/c empty from previous. So net result (cmake 3.9) is that only C/CXX openmp detected by kitware module, but only CMAKE_Fortran_FLAGS end up with any openmp flags after passing through autocmake_omp.

@bast
Copy link
Member

bast commented May 11, 2018

Thanks Lori! I will try to reproduce this.

@bast bast self-assigned this May 11, 2018
@bast
Copy link
Member

bast commented May 11, 2018

I believe there is a problem but at this moment cannot reproduce it with CMake 3.9.6 and GNU 8.1.0. I probably use a different compiler. Using which compilers do you observe this?

@loriab
Copy link
Author

loriab commented May 11, 2018

I'm on cmake 3.9.4 and gcc 7.2.0 (from conda). conda gfortran isn't providing omp_lib header or module, so that's probably why kitware findopenmp is failing to detect for Fortran, which starts the cascade.

@bast
Copy link
Member

bast commented May 11, 2018

OK thanks. It would be nice if we could query OpenMP_<lang>_FOUND but these were only introduced in 3.9.

@bast
Copy link
Member

bast commented May 11, 2018

We could for each language check whether either OpenMP_<lang>_FOUND or OpenMP_FOUND. Also the add_definitions(-DHAVE_OPENMP) seems kind of ugly from the modern CMake perspective. What is your opinion @robertodr?

@loriab
Copy link
Author

loriab commented May 11, 2018

Yes, I was just going to ask if there'd be forseeable trouble with if(${OPENMP_FOUND} OR ${OpenMP_C_FOUND}) per-language? I don't know what cmake wants in the way of quotes these days.

@bast
Copy link
Member

bast commented May 11, 2018

I expect no trouble. Not sure what to do with the add_definitions but independently of it the current problem could be solved with:

if(DEFINED CMAKE_C_COMPILER_ID)
  if(OPENMP_FOUND OR OPENMP_C_FOUND)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
  endif()
endif()

# etc. for the other languages

On the other hand the "proper" way for 3.9 and above is actually this:
https://github.com/bast/cmake-recipes/blob/master/chapter-03/recipe-05/cxx-example/CMakeLists.txt

@robertodr
Copy link
Contributor

The add_definitions should stay as-is, I think. @bast did copying the modern FindOpenMP.cmake module work for OpenMP detection? I think that would actually be the most reasonable choice...

@bast
Copy link
Member

bast commented May 11, 2018

You mean shipping the latest FindOpenMP.cmake with autocmake and checking that it works also with 2.8? Just to make sure I understand the question.

@loriab
Copy link
Author

loriab commented May 11, 2018

I'll experiment with those lines, thanks.

I'm a huge fan of the imported target in general. But I don't dare do it here b/c of the problem I was discussing with @robertodr about needing to suppress lgomp linking for GCC+MKL (this is also the problem that led to the nasty table here. So basically I want the flags out of FindOpenMP but not the link libs.

@robertodr
Copy link
Contributor

You can still get the flags out from the new module (though that might be on its way to deprecation)

@loriab
Copy link
Author

loriab commented May 11, 2018

By as-is on the definitions, you mean set when C found, @robertodr? Or potentially added three times if all langs enabled?

@robertodr
Copy link
Contributor

robertodr commented May 11, 2018

Gee, what a mess! No we definitely don't want that, so I guess either they spill over to the client:

if(OpenMP_FOUND)
  target_compile_definitions(<target-name>
     PUBLIC
        HAVE_OPENMP
     )
endif()
# or a generator expression
target_compile_definitions(<target-name>
  PUBLIC
    "$<$<BOOL:${OPENMP_FOUND}>:HAVE_OPENMP>"
  )

or it spills over to the compiler flags:

set(CXX_FLAGS ${OpenMP_CXX_FLAGS} -DHAVE_OPENMP)

quite ugly in both cases, but I'd rather prefer the former: explicit is better than implicit (of sorts) and you get to choose the name of the preprocessor definition!

@bast, yes that's what I meant. I recall it didn't work out for FindMPI.cmake. (This thread is moving very fast, I'm losing half of the comments 😸 )

@loriab
Copy link
Author

loriab commented May 11, 2018

I'm going with

    set(_omp_enabled_for_enabled_lang OFF)

    if(DEFINED CMAKE_C_COMPILER_ID)
        if(OPENMP_FOUND OR OpenMP_C_FOUND)
            set(_omp_enabled_for_enabled_lang ON)
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
        endif()
    endif()

    if(DEFINED CMAKE_CXX_COMPILER_ID)
        if(OPENMP_FOUND OR OpenMP_CXX_FOUND)
            set(_omp_enabled_for_enabled_lang ON)
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
        endif()
    endif()

    if(DEFINED CMAKE_Fortran_COMPILER_ID)
        if(OPENMP_FOUND OR OpenMP_Fortran_FOUND)
            set(_omp_enabled_for_enabled_lang ON)
            set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}")
        endif()
    endif()

    if(${_omp_enabled_for_enabled_lang})
        add_definitions(-DHAVE_OPENMP)
    endif()

@robertodr
Copy link
Contributor

Definitely more compact.

@loriab
Copy link
Author

loriab commented May 11, 2018

Well, 7 lines where there used to be 1. But I don't see another dumb way around it (classifying your sol'ns as "smart" cmake uses).

@robertodr
Copy link
Contributor

Don't know it mine was "smart". Yours is compact wrt spilling variables over to other CMake files.

@bast
Copy link
Member

bast commented May 11, 2018

For more compactness we can add a foreach looping over the languages. I think we should rename this module to omp-flags since it's really only about flags. I will test backwards compatibility of recent find module and sleep on this issue and then tomorrow comment more and/or send a PR based on our findings.

@bast
Copy link
Member

bast commented May 11, 2018

Using latest FindOpenMP.cmake with older versions of CMake does not work. Already 3.5 chokes on it.

@loriab
Copy link
Author

loriab commented May 11, 2018

Don't consider Psi4 as a an impediment to bumping min supported cmake version.

For one, all the repos have their own copies of the autocmake file. For second, someday when need is pressing and the blas/omp detection landscape is cleaner, I'll probably bump the p4 ecosystem to 3.9 or whereever all the Intel/OMP/MPI goodies are. conda is distributing 3.11 now, so access not a problem.

@bast
Copy link
Member

bast commented May 12, 2018

We (the editorial we :-) are not super sure yet which minimum we want to support (#243) but until we settle that, probably as far back as 2.8 and mostly because of more conservative codes than Psi4. I will send a PR and let you both review it and we go from there.

loriab added a commit to loriab/psi4 that referenced this issue May 13, 2018
@loriab loriab mentioned this issue May 13, 2018
7 tasks
bast added a commit to bast/autocmake that referenced this issue May 13, 2018
changes:
- append flags if either OPENMP_FOUND OR OpenMP_${_lang}_FOUND
- do not set OPENMP_FOUND
- make version dependence of workaround for CMake < 3.5 more explicit
- do not add_definitions(-DHAVE_OPENMP)
- rename to omp-flags.cmake to be more explicit and to not silently
  drop -DHAVE_OPENMP
@loriab
Copy link
Author

loriab commented May 23, 2018

FYI, cmake 3.11 (but not 3.9) gets around my initial problem by letting you specify a subset of the enabled langs to search for find_package(OpenMP COMPONENTS C CXX) and thus still merit the overall OpenMP_FOUND.

@loriab
Copy link
Author

loriab commented May 24, 2018

3.10 is the exact introduction date of the components mentioned above.

fyi, libraries returned in the OpenMP::OpenMP_CXX target for gcc are gomp;pthreads and for icpc are iomp5;pthreads, along with corresponding lang-specific COMPILE_FLAGS

 Properties for TARGET OpenMP::OpenMP_CXX:
   OpenMP::OpenMP_CXX.INTERFACE_COMPILE_OPTIONS = "$<$<COMPILE_LANGUAGE:CXX>:-fopenmp>"
   OpenMP::OpenMP_CXX.INTERFACE_LINK_LIBRARIES = "/home/psilocaluser/toolchainconda/envs/p4dev36/x86_64-conda_cos6-linux-gnu/sysroot/lib/libgomp.so;/home/psilocaluser/toolchainconda/envs/p4dev36/x86_64-conda_cos6-linux-gnu/sysroot/usr/lib/libpthread.so"

and all that can be copied into a new target via

    include(CMakePrintHelpers)
    if(TARGET OpenMP::OpenMP_CXX)
        add_library(omp_cxx INTERFACE)
        get_property(_ill TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_LINK_LIBRARIES)
        get_property(_ico TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_COMPILE_OPTIONS)
        set_property(TARGET omp_cxx PROPERTY INTERFACE_COMPILE_OPTIONS "${_ico}")
        set_property(TARGET omp_cxx PROPERTY INTERFACE_LINK_LIBRARIES "${_ill}")
        cmake_print_properties(TARGETS OpenMP::OpenMP_CXX omp_cxx
                               PROPERTIES INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_OPTIONS INTERFACE_COMPILE_FEATURES INTERFACE_INCLUDE_DIRS INTERFACE_LINK_LIBRARIES)

        message("FL: ${OpenMP_CXX_FLAGS}")
        message("LN: ${OpenMP_CXX_LIB_NAMES}")
        message("LI: ${OpenMP_CXX_LIBRARY}")
        message("LS: ${OpenMP_CXX_LIBRARIES}")
        # FL: -fopenmp
        # LN: gomp;pthread
        # LI: 
        # LS: /home/psilocaluser/toolchainconda/envs/p4dev36/x86_64-conda_cos6-linux-gnu/sysroot/lib/libgomp.so;/home/psilocaluser/toolchainconda/envs/p4dev36/x86_64-conda_cos6-linux-gnu/sysroot/usr/lib/libpthread.so
    endif()

@bast
Copy link
Member

bast commented May 25, 2018

Thank you for the information! I will revise #248.

@loriab
Copy link
Author

loriab commented Jun 1, 2018

I pinged you on psi4/psi4#1031 and would be glad of any comments on that new OpenMP-finding scheme. Most everything is centered in https://github.com/loriab/psi4/tree/openblas/external/common/lapack . The FindTargetOpenMP.cmake file within is most relevant to this autocmake issue. It finds an OpenMP target with modern cmake or constructs one to compensate in old cmake. I know autocmake doesn't deal much with targets, but the usual variables can just read off the target. Also the psi one is CXX only, so extensions would need be be made for other langs.

@bast
Copy link
Member

bast commented Jun 4, 2018

Thanks! I will look at it. Also I will finally restart work on this issue hopefully today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants