#!-------------------------------------------------------------------------------------------------!
#!   CP2K: A general program to perform molecular dynamics simulations                             !
#!   Copyright 2000-2022 CP2K developers group <https://cp2k.org>                                  !
#!                                                                                                 !
#!   SPDX-License-Identifier: GPL-2.0-or-later                                                     !
#!-------------------------------------------------------------------------------------------------!

include(fypp-sources)
include(GNUInstallDirs) # required to get a proper LIBDIR variable
include(CMakePackageConfigHelpers)

configure_file(base/base_uses.f90 base/base_uses.f90 @ONLY)

# =================================================================================================
# SOURCE FILE LISTS
# =================================================================================================

# do not worry about formatting or sorting. make pretty will fix this for you

# the sources files are split by directory which hopefully make the list a bit
# clearer. Any Fortran new file can be added to CP2K_SRCS_F list. the list
# sorted but it is *not* a requirement. C files should be added preferencially
# to CP2K_SRCS_C etc....
#
# The other option is to simply create a new list with the syntax list(APPEND
# MY_FOO foo.c foo.F foo.cu) and add this list to the list of files to compile.

list(
  APPEND
  CP2K_SRCS_F
  admm_dm_methods.F
  admm_dm_types.F
  admm_methods.F
  admm_types.F
  admm_utils.F
  almo_scf_diis_types.F
  almo_scf_env_methods.F
  almo_scf.F
  almo_scf_lbfgs_types.F
  almo_scf_methods.F
  almo_scf_optimizer.F
  almo_scf_qs.F
  almo_scf_types.F
  al_system_types.F
  atom_admm_methods.F
  atom_basis.F
  atom_electronic_structure.F
  atom_energy.F
  atom.F
  atom_fit.F
  atom_grb.F
  atomic_charges.F
  atom_kind_orbitals.F
  atom_operators.F
  atom_optimization.F
  atom_output.F
  atom_pseudo.F
  atom_sgp.F
  atoms_input.F
  atom_types.F
  atom_upf.F
  atom_utils.F
  atom_xc.F
  auto_basis.F
  basis_set_output.F
  beta_gamma_psi.F
  block_p_types.F
  bse.F
  bsse.F
  cell_methods.F
  colvar_methods.F
  colvar_utils.F
  commutator_rkinetic.F
  commutator_rpnl.F
  constraint_3x3.F
  constraint_4x6.F
  constraint_clv.F
  constraint.F
  constraint_fxd.F
  constraint_util.F
  constraint_vsite.F
  core_ae.F
  core_ppl.F
  core_ppnl.F
  cp2k_debug.F
  cp2k_info.F
  cp_control_types.F
  cp_control_utils.F
  cp_dbcsr_cholesky.F
  cp_dbcsr_cp2k_link.F
  cp_dbcsr_diag.F
  cp_dbcsr_operations.F
  cp_dbcsr_output.F
  cp_ddapc.F
  cp_ddapc_forces.F
  cp_ddapc_methods.F
  cp_ddapc_types.F
  cp_ddapc_util.F
  cp_eri_mme_interface.F
  cp_external_control.F
  parallel_gemm_api.F
  cp_realspace_grid_cube.F
  cp_realspace_grid_init.F
  cp_subsys_methods.F
  cp_symmetry.F
  cryssym.F
  csvr_system_types.F
  csvr_system_utils.F
  ct_methods.F
  ct_types.F
  debug_os_integrals.F
  dft_plus_u.F
  dgemm_counter_types.F
  distribution_2d_types.F
  distribution_methods.F
  dkh_main.F
  dm_ls_chebyshev.F
  dm_ls_scf_create.F
  dm_ls_scf_curvy.F
  dm_ls_scf.F
  dm_ls_scf_methods.F
  dm_ls_scf_qs.F
  dm_ls_scf_types.F
  domain_submatrix_methods.F
  domain_submatrix_types.F
  ec_efield_local.F
  ec_environment.F
  ec_env_types.F
  ec_methods.F
  ec_orth_solver.F
  efield_tb_methods.F
  efield_utils.F
  eip_environment.F
  eip_environment_types.F
  eip_silicon.F
  embed_environment.F
  embed_main.F
  embed_types.F
  energy_corrections.F
  environment.F
  eri_mme/eri_mme_error_control.F
  eri_mme/eri_mme_gaussian.F
  eri_mme/eri_mme_integrate.F
  eri_mme/eri_mme_lattice_summation.F
  eri_mme/eri_mme_test.F
  eri_mme/eri_mme_types.F
  eri_mme/eri_mme_util.F
  et_coupling.F
  et_coupling_proj.F
  et_coupling_types.F
  ewald_environment_types.F
  ewald_methods_tb.F
  ewald_pw_methods.F
  ewald_pw_types.F
  ewalds.F
  ewalds_multipole.F
  ewald_spline_util.F
  excited_states.F
  exclusion_types.F
  ex_property_calculation.F
  exstates_types.F
  extended_system_types.F
  external_potential_methods.F
  f77_interface.F
  farming_methods.F
  farming_types.F
  fermi_utils.F
  fist_efield_methods.F
  fist_efield_types.F
  fist_energy_types.F
  fist_environment.F
  fist_environment_types.F
  fist_force.F
  fist_intra_force.F
  fist_main.F
  fist_neighbor_list_control.F
  fist_neighbor_lists.F
  fist_neighbor_list_types.F
  fist_nonbond_env_types.F
  fist_nonbond_force.F
  fist_pol_scf.F
  force_env_methods.F
  force_env_types.F
  force_env_utils.F
  force_fields_all.F
  force_fields_ext.F
  force_fields.F
  force_fields_input.F
  force_fields_util.F
  force_field_types.F
  fp_methods.F
  fp_types.F
  free_energy_types.F
  generic_os_integrals.F
  gle_system_types.F
  global_types.F
  graphcon.F
  grid/grid_api.F
  group_dist_types.F
  grrm_utils.F
  hartree_local_methods.F
  hartree_local_types.F
  header.F
  hfx_admm_utils.F
  hfx_communication.F
  hfx_compression_methods.F
  hfx_derivatives.F
  hfx_energy_potential.F
  hfx_helpers.F
  hfx_libint_interface.F
  hfx_load_balance_methods.F
  hfx_pair_list_methods.F
  hfx_pw_methods.F
  hfx_ri.F
  hfx_screening_methods.F
  hfx_types.F
  hirshfeld_methods.F
  hirshfeld_types.F
  input_constants.F
  input_cp2k_almo.F
  input_cp2k_atom.F
  input_cp2k_atprop.F
  input_cp2k_binary_restarts.F
  input_cp2k_check.F
  input_cp2k_colvar.F
  input_cp2k_constraints.F
  input_cp2k_dft.F
  input_cp2k_distribution.F
  input_cp2k_ec.F
  input_cp2k_eip.F
  input_cp2k_embed.F
  input_cp2k_exstate.F
  input_cp2k_external.F
  input_cp2k_field.F
  input_cp2k_force_eval.F
  input_cp2k_free_energy.F
  input_cp2k_global.F
  input_cp2k_hfx.F
  input_cp2k_kpoints.F
  input_cp2k_loc.F
  input_cp2k_ls.F
  input_cp2k_mixed.F
  input_cp2k_mm.F
  input_cp2k_motion_print.F
  input_cp2k_mp2.F
  input_cp2k_neb.F
  input_cp2k_negf.F
  input_cp2k_nnp.F
  input_cp2k_poisson.F
  input_cp2k_properties_dft.F
  input_cp2k_pwdft.F
  input_cp2k_qmmm.F
  input_cp2k_read.F
  input_cp2k_resp.F
  input_cp2k_restarts_util.F
  input_cp2k_rsgrid.F
  input_cp2k_subsys.F
  input_cp2k_tb.F
  input_cp2k_thermostats.F
  input_cp2k_transport.F
  input_cp2k_voronoi.F
  input_cp2k_xc.F
  input_optimize_basis.F
  input_optimize_input.F
  input_restart_force_eval.F
  input_restart_rng.F
  integration_grid_types.F
  ipi_driver.F
  iterate_matrix.F
  kg_correction.F
  kg_environment.F
  kg_environment_types.F
  kg_tnadd_mat.F
  kg_vertex_coloring_methods.F
  kpoint_coulomb_2c.F
  kpoint_io.F
  kpoint_methods.F
  kpoint_transitional.F
  kpoint_types.F
  libint_2c_3c.F
  libint_wrapper.F
  library_tests.F
  linesearch.F
  localization_tb.F
  lri_compression.F
  lri_environment_init.F
  lri_environment_methods.F
  lri_environment_types.F
  lri_forces.F
  lri_integrals.F
  lri_ks_methods.F
  lri_optimize_ri_basis.F
  lri_optimize_ri_basis_types.F
  ls_matrix_exp.F
  manybody_eam.F
  manybody_gal21.F
  manybody_gal.F
  manybody_potential.F
  manybody_quip.F
  manybody_siepmann.F
  manybody_tersoff.F
  mao_basis.F
  mao_methods.F
  mao_optimizer.F
  mao_types.F
  mao_wfn_analysis.F
  matrix_exp.F
  maxwell_solver_interface.F
  mdctrl_types.F
  metadynamics.F
  metadynamics_types.F
  metadynamics_utils.F
  metadyn_tools/graph_methods.F
  metadyn_tools/graph_utils.F
  minbas_methods.F
  minbas_wfn_analysis.F
  mixed_cdft_methods.F
  mixed_cdft_types.F
  mixed_cdft_utils.F
  mixed_energy_types.F
  mixed_environment.F
  mixed_environment_types.F
  mixed_environment_utils.F
  mixed_main.F
  mm_collocate_potential.F
  mm_mapping_library.F
  mode_selective.F
  molden_utils.F
  molecular_dipoles.F
  molecular_moments.F
  molecular_states.F
  mol_force.F
  molsym.F
  moments_utils.F
  motion_utils.F
  mp2_cphf.F
  mp2_direct_method.F
  mp2_eri.F
  mp2_eri_gpw.F
  mp2.F
  mp2_gpw.F
  mp2_gpw_method.F
  mp2_grids.F
  mp2_integrals.F
  mp2_laplace.F
  mp2_optimize_ri_basis.F
  mp2_ri_2c.F
  mp2_ri_gpw.F
  mp2_ri_grad.F
  mp2_ri_grad_util.F
  mp2_ri_libint.F
  mp2_setup.F
  mp2_types.F
  mpiwrap/message_passing.F
  mscfg_methods.F
  mscfg_types.F
  mulliken.F
  negf_alloc_types.F
  negf_atom_map.F
  negf_control_types.F
  negf_env_types.F
  negf_green_cache.F
  negf_green_methods.F
  negf_integr_cc.F
  negf_integr_simpson.F
  negf_integr_utils.F
  negf_matrix_utils.F
  negf_methods.F
  negf_subgroup_types.F
  negf_vectors.F
  nnp_acsf.F
  nnp_environment.F
  nnp_environment_types.F
  nnp_force.F
  nnp_model.F
  local_gemm_api.F
  offload/offload_api.F
  optbas_fenv_manipulation.F
  optbas_opt_utils.F
  optimize_basis.F
  optimize_basis_types.F
  optimize_basis_utils.F
  optimize_dmfet_potential.F
  optimize_embedding_potential.F
  optimize_input.F
  outer_scf_control_types.F
  pair_potential_coulomb.F
  pair_potential.F
  pair_potential_types.F
  pair_potential_util.F
  pao_input.F
  pao_io.F
  pao_linpot_full.F
  pao_linpot_rotinv.F
  pao_main.F
  pao_methods.F
  pao_ml_descriptor.F
  pao_ml.F
  pao_ml_gaussprocess.F
  pao_ml_neuralnet.F
  pao_optimizer.F
  pao_param_exp.F
  pao_param.F
  pao_param_fock.F
  pao_param_gth.F
  pao_param_linpot.F
  pao_potentials.F
  pao_types.F
  particle_methods.F
  paw_proj_set_types.F
  pexsi_interface.F
  pexsi_methods.F
  pexsi_types.F
  pilaenv_hack.F
  pme.F
  pme_tools.F
  population_analyses.F
  preconditioner_apply.F
  preconditioner.F
  preconditioner_makes.F
  preconditioner_solvers.F
  preconditioner_types.F
  qmmm_create.F
  qmmm_elpot.F
  qmmm_ff_fist.F
  qmmm_force.F
  qmmm_gaussian_data.F
  qmmm_gaussian_init.F
  qmmm_gaussian_input.F
  qmmm_gaussian_types.F
  qmmm_gpw_energy.F
  qmmm_gpw_forces.F
  qmmm_image_charge.F
  qmmm_init.F
  qmmm_links_methods.F
  qmmm_per_elpot.F
  qmmm_pw_grid.F
  qmmm_se_energy.F
  qmmm_se_forces.F
  qmmm_tb_coulomb.F
  qmmm_tb_methods.F
  qmmm_topology_util.F
  qmmm_types.F
  qmmm_types_low.F
  qmmm_util.F
  qmmmx_create.F
  qmmmx_force.F
  qmmmx_types.F
  qmmmx_update.F
  qmmmx_util.F
  qs_2nd_kernel_ao.F
  qs_active_space_methods.F
  qs_active_space_types.F
  qs_atomic_block.F
  qs_band_structure.F
  qs_basis_gradient.F
  qs_block_davidson_types.F
  qs_cdft_methods.F
  qs_cdft_opt_types.F
  qs_cdft_scf_utils.F
  qs_cdft_types.F
  qs_cdft_utils.F
  qs_charge_mixing.F
  qs_chargemol.F
  qs_charges_types.F
  qs_collocate_density.F
  qs_commutators.F
  qs_condnum.F
  qs_core_energies.F
  qs_core_hamiltonian.F
  qs_dcdr_ao.F
  qs_dcdr.F
  qs_dcdr_utils.F
  qs_density_matrices.F
  qs_density_mixing_types.F
  qs_dftb3_methods.F
  qs_dftb_coulomb.F
  qs_dftb_dispersion.F
  qs_dftb_matrices.F
  qs_dftb_parameters.F
  qs_dftb_types.F
  qs_dftb_utils.F
  qs_diis.F
  qs_diis_types.F
  qs_dispersion_nonloc.F
  qs_dispersion_pairpot.F
  qs_dispersion_types.F
  qs_dispersion_utils.F
  qs_dos.F
  qs_efield_berry.F
  qs_efield_local.F
  qs_elec_field.F
  qs_electric_field_gradient.F
  qs_elf_methods.F
  qs_energy.F
  qs_energy_init.F
  qs_energy_matrix_w.F
  qs_energy_types.F
  qs_energy_utils.F
  qs_energy_window.F
  qs_environment.F
  qs_environment_methods.F
  qs_environment_types.F
  qs_epr_hyp.F
  qs_external_density.F
  qs_external_potential.F
  qs_fb_atomic_halo_types.F
  qs_fb_atomic_matrix_methods.F
  qs_fb_buffer_types.F
  qs_fb_com_tasks_types.F
  qs_fb_distribution_methods.F
  qs_fb_env_methods.F
  qs_fb_env_types.F
  qs_fb_filter_matrix_methods.F
  qs_fb_hash_table_types.F
  qs_fb_input.F
  qs_fb_matrix_data_types.F
  qs_fb_trial_fns_types.F
  qs_fermi_contact.F
  qs_force.F
  qs_force_types.F
  qs_fxc.F
  qs_gamma2kp.F
  qs_gapw_densities.F
  qs_gcp_method.F
  qs_gcp_types.F
  qs_gcp_utils.F
  qs_grid_atom.F
  qs_gspace_mixing.F
  qs_harmonics_atom.F
  qs_hash_table_functions.F
  qs_initial_guess.F
  qs_integral_utils.F
  qs_integrate_potential.F
  qs_integrate_potential_product.F
  qs_integrate_potential_single.F
  qs_interactions.F
  qs_kernel_methods.F
  qs_kernel_types.F
  qs_kind_types.F
  qs_kinetic.F
  qs_kpp1_env_methods.F
  qs_kpp1_env_types.F
  qs_ks_apply_restraints.F
  qs_ks_atom.F
  qs_ks_methods.F
  qs_ks_qmmm_methods.F
  qs_ks_qmmm_types.F
  qs_ks_types.F
  qs_ks_utils.F
  qs_ks_reference.F
  qs_linres_atom_current.F
  qs_linres_current.F
  qs_linres_current_utils.F
  qs_linres_epr_nablavks.F
  qs_linres_epr_ownutils.F
  qs_linres_epr_utils.F
  qs_linres_issc_utils.F
  qs_linres_kernel.F
  qs_linres_methods.F
  qs_linres_module.F
  qs_linres_nmr_epr_common_utils.F
  qs_linres_nmr_shift.F
  qs_linres_nmr_utils.F
  qs_linres_op.F
  qs_linres_polar_utils.F
  qs_linres_types.F
  qs_localization_methods.F
  qs_local_properties.F
  qs_local_rho_types.F
  qs_loc_dipole.F
  qs_loc_methods.F
  qs_loc_molecules.F
  qs_loc_states.F
  qs_loc_types.F
  qs_loc_utils.F
  qs_matrix_pools.F
  qs_matrix_w.F
  qs_mixing_utils.F
  qs_mo_io.F
  qs_moments.F
  qs_mo_methods.F
  qs_mom_methods.F
  qs_mom_types.F
  qs_mo_occupation.F
  qs_mo_types.F
  qs_neighbor_lists.F
  qs_neighbor_list_types.F
  qs_nl_hash_table_types.F
  qs_o3c_methods.F
  qs_o3c_types.F
  qs_oce_methods.F
  qs_oce_types.F
  qs_operators_ao.F
  qs_ot_eigensolver.F
  qs_ot.F
  qs_ot_minimizer.F
  qs_ot_scf.F
  qs_ot_types.F
  qs_outer_scf.F
  qs_overlap.F
  qs_pdos.F
  qs_p_env_methods.F
  qs_p_env_types.F
  qs_period_efield_types.F
  qs_resp.F
  qs_rho0_ggrid.F
  qs_rho0_methods.F
  qs_rho0_types.F
  qs_rho_atom_methods.F
  qs_rho_atom_types.F
  qs_rho_methods.F
  qs_rho_types.F
  qs_sccs.F
  qs_scf_block_davidson.F
  qs_scf_csr_write.F
  qs_scf_diagonalization.F
  qs_scf.F
  qs_scf_initialization.F
  qs_scf_lanczos.F
  qs_scf_loop_utils.F
  qs_scf_methods.F
  qs_scf_output.F
  qs_scf_post_gpw.F
  qs_scf_post_scf.F
  qs_scf_post_se.F
  qs_scf_post_tb.F
  qs_scf_types.F
  qs_scf_wfn_mix.F
  qs_spin_orbit.F
  qs_subsys_methods.F
  qs_subsys_types.F
  qs_tddfpt2_densities.F
  qs_tddfpt2_eigensolver.F
  qs_tddfpt2_fhxc.F
  qs_tddfpt2_fhxc_forces.F
  qs_tddfpt2_forces.F
  qs_tddfpt2_lri_utils.F
  qs_tddfpt2_methods.F
  qs_tddfpt2_operators.F
  qs_tddfpt2_properties.F
  qs_tddfpt2_restart.F
  qs_tddfpt2_stda_types.F
  qs_tddfpt2_stda_utils.F
  qs_tddfpt2_subgroups.F
  qs_tddfpt2_types.F
  qs_tddfpt2_utils.F
  qs_tddfpt_eigensolver.F
  qs_tddfpt_module.F
  qs_tddfpt_types.F
  qs_tddfpt_utils.F
  qs_tddfpt2_fprint.F
  qs_tensors.F
  qs_tensors_types.F
  qs_update_s_mstruct.F
  qs_vxc_atom.F
  qs_vxc.F
  qs_wannier90.F
  qs_wf_history_methods.F
  qs_wf_history_types.F
  rel_control_types.F
  replica_methods.F
  replica_types.F
  response_solver.F
  restraint.F
  ri_environment_methods.F
  rmsd.F
  rpa_axk.F
  rpa_communication.F
  rpa_grad.F
  rpa_gw.F
  rpa_gw_ic.F
  rpa_gw_im_time_util.F
  rpa_gw_kpoints_util.F
  rpa_gw_sigma_x.F
  rpa_hfx.F
  rpa_im_time.F
  rpa_main.F
  rpa_rse.F
  rpa_im_time_force_types.F
  rpa_im_time_force_methods.F
  rpa_util.F
  rtp_admm_methods.F
  rt_propagation_forces.F
  rt_propagation_types.F
  rt_propagation_velocity_gauge.F
  sap_kind_types.F
  scf_control_types.F
  scine_utils.F
  se_core_core.F
  se_core_matrix.F
  se_fock_matrix_coulomb.F
  se_fock_matrix_dbg.F
  se_fock_matrix_exchange.F
  se_fock_matrix.F
  se_fock_matrix_integrals.F
  semi_empirical_expns3_methods.F
  semi_empirical_expns3_types.F
  semi_empirical_int3_utils.F
  semi_empirical_int_ana.F
  semi_empirical_int_arrays.F
  semi_empirical_int_debug.F
  semi_empirical_integrals.F
  semi_empirical_int_gks.F
  semi_empirical_int_num.F
  semi_empirical_int_utils.F
  semi_empirical_mpole_methods.F
  semi_empirical_mpole_types.F
  semi_empirical_parameters.F
  semi_empirical_par_utils.F
  semi_empirical_store_int_types.F
  semi_empirical_types.F
  semi_empirical_utils.F
  simpar_types.F
  sirius_interface.F
  spglib_f08.F
  splines_methods.F
  splines_types.F
  spme.F
  s_square_methods.F
  statistical_methods.F
  stm_images.F
  subcell_types.F
  submatrix_dissection.F
  submatrix_types.F
  surface_dipole.F
  taper_types.F
  task_list_methods.F
  task_list_types.F
  tip_scan_methods.F
  tip_scan_types.F
  topology_amber.F
  topology_cif.F
  topology_connectivity_util.F
  topology_constraint_util.F
  topology_coordinate_util.F
  topology_cp2k.F
  topology.F
  topology_generate_util.F
  topology_gromos.F
  topology_input.F
  topology_multiple_unit_cell.F
  topology_pdb.F
  topology_psf.F
  topology_types.F
  topology_util.F
  topology_xtl.F
  topology_xyz.F
  transport_env_types.F
  transport.F
  uff_vdw_radii_table.F
  virial_methods.F
  voronoi_interface.F
  wannier90.F
  wannier_states.F
  wannier_states_types.F
  xas_control.F
  xas_env_types.F
  xas_methods.F
  xas_restart.F
  xas_tdp_atom.F
  xas_tdp_correction.F
  xas_tdp_integrals.F
  xas_tdp_kernel.F
  xas_tdp_methods.F
  xas_tdp_types.F
  xas_tdp_utils.F
  xas_tp_scf.F
  xray_diffraction.F
  xtb_coulomb.F
  xtb_ehess.F
  xtb_ehess_force.F
  xtb_matrices.F
  xtb_parameters.F
  xtb_types.F)

list(
  APPEND
  CP2K_SRCS_F
  aobasis/ai_angmom.F
  aobasis/ai_contraction.F
  aobasis/ai_contraction_sphi.F
  aobasis/ai_coulomb.F
  aobasis/ai_coulomb_test.F
  aobasis/ai_derivatives.F
  aobasis/ai_elec_field.F
  aobasis/ai_eri_debug.F
  aobasis/ai_fermi_contact.F
  aobasis/ai_kinetic.F
  aobasis/ai_moments.F
  aobasis/ai_onecenter.F
  aobasis/ai_oneelectron.F
  aobasis/ai_operator_ra2m.F
  aobasis/ai_operators_r12.F
  aobasis/ai_os_rr.F
  aobasis/ai_overlap3_debug.F
  aobasis/ai_overlap3.F
  aobasis/ai_overlap_aabb.F
  aobasis/ai_overlap_debug.F
  aobasis/ai_overlap.F
  aobasis/ai_overlap_ppl.F
  aobasis/ai_spin_orbit.F
  aobasis/ai_verfc.F
  aobasis/ao_util.F
  aobasis/aux_basis_set.F
  aobasis/basis_set_container_types.F
  aobasis/basis_set_types.F
  aobasis/orbital_pointers.F
  aobasis/orbital_symbols.F
  aobasis/orbital_transformation_matrices.F
  aobasis/soft_basis_set.F
  aobasis/sto_ng.F)

list(
  APPEND
  CP2K_SRCS_F
  arnoldi/arnoldi_api.F
  arnoldi/arnoldi_data_methods.F
  arnoldi/arnoldi_geev.F
  arnoldi/arnoldi_methods.F
  arnoldi/arnoldi_types.F)

list(APPEND CP2K_SRCS_F base/base_hooks.F base/kinds.F base/machine.F)

list(
  APPEND
  CP2K_SRCS_F
  common/bessel_lib.F
  common/bibliography.F
  common/callgraph.F
  common/cg_test.F
  common/cp_array_sort.F
  common/cp_array_utils.F
  common/cp_error_handling.F
  common/cp_files.F
  common/cp_iter_types.F
  common/cp_log_handling.F
  common/cp_min_heap.F
  common/cp_para_env.F
  common/cp_para_types.F
  common/cp_result_methods.F
  common/cp_result_types.F
  common/cp_units.F
  common/d3_poly.F
  common/distribution_1d_types.F
  common/eigenvalueproblems.F
  common/fparser.F
  common/gamma.F
  common/kahan_sum.F
  common/lapack.F
  common/lebedev.F
  common/linear_systems.F
  common/list_callstackentry.F
  common/list.F
  common/list_routinereport.F
  common/list_routinestat.F
  common/list_timerenv.F
  common/mathconstants.F
  common/mathlib.F
  common/memory_utilities.F
  common/parallel_rng_types.F
  common/periodic_table.F
  common/physcon.F
  common/powell.F
  common/print_messages.F
  common/reference_manager.F
  common/routine_map.F
  common/spherical_harmonics.F
  common/splines.F
  common/string_table.F
  common/string_utilities.F
  common/structure_factors.F
  common/structure_factor_types.F
  common/t_c_g0.F
  common/timings_base_type.F
  common/timings.F
  common/timings_report.F
  common/timings_types.F
  common/t_sh_p_s_c.F
  common/util.F
  common/whittaker.F)

list(APPEND CP2K_SRCS_F dbcsrx/dbcsr_vector.F)

list(APPEND CP2K_SRCS_F dbm/dbm_api.F dbm/dbm_tests.F)

list(
  APPEND
  CP2K_SRCS_F
  dbt/dbt_allocate_wrap.F
  dbt/dbt_api.F
  dbt/dbt_array_list_methods.F
  dbt/dbt_block.F
  dbt/dbt_index.F
  dbt/dbt_io.F
  dbt/dbt_methods.F
  dbt/dbt_reshape_ops.F
  dbt/dbt_split.F
  dbt/dbt_types.F
  dbt/tas/dbt_tas_base.F
  dbt/tas/dbt_tas_global.F
  dbt/tas/dbt_tas_io.F
  dbt/tas/dbt_tas_mm.F
  dbt/tas/dbt_tas_reshape_ops.F
  dbt/tas/dbt_tas_split.F
  dbt/tas/dbt_tas_types.F
  dbt/tas/dbt_tas_util.F
  dbt/dbt_test.F
  dbt/tas/dbt_tas_test.F)

list(
  APPEND
  CP2K_SRCS_F
  emd/rt_delta_pulse.F
  emd/rt_hfx_utils.F
  emd/rt_make_propagators.F
  emd/rt_propagation_methods.F
  emd/rt_propagation_output.F
  emd/rt_propagation_utils.F
  emd/rt_propagator_init.F)

list(
  APPEND
  CP2K_SRCS_F
  fm/cp_blacs_calls.F
  fm/cp_blacs_env.F
  fm/cp_cfm_basic_linalg.F
  fm/cp_cfm_diag.F
  fm/cp_cfm_types.F
  fm/cp_fm_basic_linalg.F
  fm/cp_fm_cholesky.F
  fm/cp_fm_diag.F
  fm/cp_fm_diag_utils.F
  fm/cp_fm_elpa.F
  fm/cp_fm_pool_types.F
  fm/cp_fm_struct.F
  fm/cp_fm_types.F
  fm/cp_fm_vect.F
  fm/cp_linked_list_fm.F)

list(APPEND CP2K_SRCS_F hfxbase/hfx_compression_core_methods.F
     hfxbase/hfx_contract_block.F hfxbase/hfx_contraction_methods.F)

list(
  APPEND
  CP2K_SRCS_F
  input/cp_linked_list_input.F
  input/cp_output_handling.F
  input/cp_parser_buffer_types.F
  input/cp_parser_ilist_methods.F
  input/cp_parser_ilist_types.F
  input/cp_parser_inpp_methods.F
  input/cp_parser_inpp_types.F
  input/cp_parser_methods.F
  input/cp_parser_status_types.F
  input/cp_parser_types.F
  input/input_enumeration_types.F
  input/input_keyword_types.F
  input/input_parsing.F
  input/input_section_types.F
  input/input_val_types.F)

list(
  APPEND
  CP2K_SRCS_F
  minimax/minimax_exp.F
  minimax/minimax_exp_gw.F
  minimax/minimax_exp_k15.F
  minimax/minimax_exp_k53.F
  minimax/minimax_rpa.F)

list(
  APPEND
  CP2K_SRCS_F
  motion/averages_types.F
  motion/bfgs_optimizer.F
  motion/cell_opt.F
  motion/cell_opt_types.F
  motion/cell_opt_utils.F
  motion/cg_optimizer.F
  motion/cg_utils.F
  motion/cp_lbfgs.F
  motion/cp_lbfgs_geo.F
  motion/cp_lbfgs_optimizer_gopt.F
  motion/dimer_methods.F
  motion/dimer_types.F
  motion/dimer_utils.F
  motion/free_energy_methods.F
  motion/geo_opt.F
  motion/glbopt_callback.F
  motion/gopt_f77_methods.F
  motion/gopt_f_methods.F
  motion/gopt_f_types.F
  motion/gopt_param_types.F
  motion/helium_common.F
  motion/helium_interactions.F
  motion/helium_io.F
  motion/helium_methods.F
  motion/helium_sampling.F
  motion/helium_types.F
  motion/helium_worm.F
  motion/input_cp2k_md.F
  motion/input_cp2k_restarts.F
  motion/input_cp2k_vib.F
  motion/integrator.F
  motion/integrator_utils.F
  motion/mc/mc_control.F
  motion/mc/mc_coordinates.F
  motion/mc/mc_ensembles.F
  motion/mc/mc_environment_types.F
  motion/mc/mc_ge_moves.F
  motion/mc/mc_misc.F
  motion/mc/mc_move_control.F
  motion/mc/mc_moves.F
  motion/mc/mc_run.F
  motion/mc/mc_types.F
  motion/mc/tamc_run.F
  motion/md_conserved_quantities.F
  motion/mdctrl_methods.F
  motion/md_energies.F
  motion/md_ener_types.F
  motion/md_environment_types.F
  motion/md_run.F
  motion/md_util.F
  motion/md_vel_utils.F
  motion/neb_io.F
  motion/neb_md_utils.F
  motion/neb_methods.F
  motion/neb_opt_utils.F
  motion/neb_types.F
  motion/neb_utils.F
  motion/pint_gle.F
  motion/pint_io.F
  motion/pint_methods.F
  motion/pint_normalmode.F
  motion/pint_piglet.F
  motion/pint_pile.F
  motion/pint_public.F
  motion/pint_qtb.F
  motion/pint_staging.F
  motion/pint_transformations.F
  motion/pint_types.F
  motion/reftraj_types.F
  motion/reftraj_util.F
  motion/rt_propagation.F
  motion/shell_opt.F
  motion/simpar_methods.F
  motion/space_groups.F
  motion/space_groups_types.F
  motion/thermal_region_types.F
  motion/thermal_region_utils.F
  motion/thermostat/al_system_dynamics.F
  motion/thermostat/al_system_init.F
  motion/thermostat/al_system_mapping.F
  motion/thermostat/barostat_types.F
  motion/thermostat/barostat_utils.F
  motion/thermostat/csvr_system_dynamics.F
  motion/thermostat/csvr_system_init.F
  motion/thermostat/csvr_system_mapping.F
  motion/thermostat/extended_system_dynamics.F
  motion/thermostat/extended_system_init.F
  motion/thermostat/extended_system_mapping.F
  motion/thermostat/gle_system_dynamics.F
  motion/thermostat/input_cp2k_barostats.F
  motion/thermostat/thermostat_mapping.F
  motion/thermostat/thermostat_methods.F
  motion/thermostat/thermostat_types.F
  motion/thermostat/thermostat_utils.F
  motion/velocity_verlet_control.F
  motion/vibrational_analysis.F
  motion/wiener_process.F)

list(
  APPEND
  CP2K_SRCS_F
  pw/cp_linked_list_pw.F
  pw/cube_utils.F
  pw/dct.F
  pwdft_environment.F
  pwdft_environment_types.F
  pw/dg_rho0_types.F
  pw/dgs.F
  pw/dg_types.F
  pw/dielectric_methods.F
  pw/dielectric_types.F
  pw/dirichlet_bc_methods.F
  pw/dirichlet_bc_types.F
  pw_env/cp_spline_utils.F
  pw_env/gaussian_gridlevels.F
  pw_env_methods.F
  pw_env/pw_env_types.F
  pw_env/rs_pw_interface.F
  pw/fast.F
  pw/fft/fft_kinds.F
  pw/fft/fft_lib.F
  pw/fft/fft_plan.F
  pw/fft/fftsg_lib.F
  pw/fft/fftw3_lib.F
  pw/fft/mltfftsg_tools.F
  pw/fft_tools.F
  pw/lazy.F
  pw/mt_util.F
  pw_poisson_read_input.F
  pw/ps_implicit_methods.F
  pw/ps_implicit_types.F
  pw/ps_wavelet_base.F
  pw/ps_wavelet_fft3d.F
  pw/ps_wavelet_kernel.F
  pw/ps_wavelet_methods.F
  pw/ps_wavelet_scaling_function.F
  pw/ps_wavelet_types.F
  pw/ps_wavelet_util.F
  pw/pw_copy_all.F
  pw/pw_fpga.F
  pw/pw_grid_info.F
  pw/pw_grids.F
  pw/pw_gpu.F
  pw/pw_grid_types.F
  pw/pw_methods.F
  pw/pw_poisson_methods.F
  pw/pw_poisson_types.F
  pw/pw_pool_types.F
  pw/pw_spline_utils.F
  pw/pw_types.F
  pw/realspace_grid_cube.F
  pw/realspace_grid_types.F
  pw/rs_methods.F)

if(CP2K_USE_PW_GPU)
  list(APPEND CP2K_SRCS_F pw/pw_gpu.F)
endif()

list(
  APPEND
  CP2K_SRCS_F
  shg_int/constants_operator.F
  shg_int/construct_shg.F
  shg_integrals_test.F
  shg_int/generic_shg_integrals.F
  shg_int/generic_shg_integrals_init.F
  shg_int/s_contract_shg.F)

list(
  APPEND
  CP2K_SRCS_F
  start/cp2k_runs.F
  start/cp2k_shell.F
  start/input_cp2k.F
  start/input_cp2k_motion.F
  start/libcp2k.F)

list(
  APPEND
  CP2K_SRCS_F
  subsys/atomic_kind_list_types.F
  subsys/atomic_kind_types.F
  subsys/atprop_types.F
  subsys/cell_types.F
  subsys/colvar_types.F
  subsys/cp_subsys_types.F
  subsys/damping_dipole_types.F
  subsys/external_potential_types.F
  subsys/force_field_kind_types.F
  subsys/molecule_kind_list_types.F
  subsys/molecule_kind_types.F
  subsys/molecule_list_types.F
  subsys/molecule_types.F
  subsys/multipole_types.F
  subsys/particle_list_types.F
  subsys/particle_types.F
  subsys/shell_potential_types.F
  subsys/virial_types.F)

list(
  APPEND
  CP2K_SRCS_F
  swarm/glbopt_history.F
  swarm/glbopt_input.F
  swarm/glbopt_master.F
  swarm/glbopt_mincrawl.F
  swarm/glbopt_minhop.F
  swarm/glbopt_worker.F
  swarm/swarm.F
  swarm/swarm_input.F
  swarm/swarm_master.F
  swarm/swarm_message.F
  swarm/swarm_mpi.F
  swarm/swarm_worker.F)

list(
  APPEND
  CP2K_SRCS_F
  tmc/input_cp2k_tmc.F
  tmc/tmc_analysis.F
  tmc/tmc_analysis_types.F
  tmc/tmc_calculations.F
  tmc/tmc_cancelation.F
  tmc/tmc_dot_tree.F
  tmc/tmc_file_io.F
  tmc/tmc_master.F
  tmc/tmc_messages.F
  tmc/tmc_move_handle.F
  tmc/tmc_moves.F
  tmc/tmc_move_types.F
  tmc/tmc_setup.F
  tmc/tmc_stati.F
  tmc/tmc_tree_acceptance.F
  tmc/tmc_tree_build.F
  tmc/tmc_tree_references.F
  tmc/tmc_tree_search.F
  tmc/tmc_tree_types.F
  tmc/tmc_types.F
  tmc/tmc_utils.F
  tmc/tmc_worker.F)

list(
  APPEND
  CP2K_SRCS_F
  xc_adiabatic_methods.F
  xc_adiabatic_utils.F
  xc/cp_linked_list_xc_deriv.F
  xc_pot_saop.F
  xc_write_output.F
  xc/xc_atom.F
  xc/xc_b97.F
  xc/xc_cs1.F
  xc/xc_derivative_desc.F
  xc/xc_derivative_set_types.F
  xc/xc_derivatives.F
  xc/xc_derivative_types.F
  xc/xc_exchange_gga.F
  xc/xc.F
  xc/xc_functionals_utilities.F
  xc/xc_hcth.F
  xc/xc_input_constants.F
  xc/xc_ke_gga.F
  xc/xc_libxc.F
  xc/xc_libxc_wrap.F
  xc/xc_lyp_adiabatic.F
  xc/xc_lyp.F
  xc/xc_optx.F
  xc/xc_pade.F
  xc/xc_pbe.F
  xc/xc_perdew86.F
  xc/xc_perdew_wang.F
  xc/xc_perdew_zunger.F
  xc/xc_rho_cflags_types.F
  xc/xc_rho_set_types.F
  xc/xc_tfw.F
  xc/xc_thomas_fermi.F
  xc/xc_tpss.F
  xc/xc_util.F
  xc/xc_vwn.F
  xc/xc_xalpha.F
  xc/xc_xbecke88.F
  xc/xc_xbecke88_long_range.F
  xc/xc_xbecke88_lr_adiabatic.F
  xc/xc_xbecke_roussel.F
  xc/xc_xbeef.F
  xc/xc_xbr_pbe_lda_hole_t_c_lr.F
  xc/xc_xlda_hole_t_c_lr.F
  xc/xc_xpbe_hole_t_c_lr.F
  xc/xc_xwpbe.F)

list(APPEND CP2K_SRCS_C base/machine_cpuid.c pw/fpga/fft_fpga.c
     pw/fpga/opencl_utils.c sockets.c)

list(
  APPEND
  DBM_SRCS_C
  dbm/dbm_distribution.c
  dbm/dbm_library.c
  dbm/dbm_matrix.c
  dbm/dbm_mempool.c
  dbm/dbm_mpi.c
  dbm/dbm_multiply.c
  dbm/dbm_multiply_comm.c
  dbm/dbm_multiply_cpu.c
  dbm/dbm_shard.c)

list(
  APPEND
  GRID_SRCS_C
  grid/common/grid_basis_set.c
  grid/common/grid_library.c
  grid/common/grid_sphere_cache.c
  grid/cpu/coefficients.c
  grid/cpu/collocation_integration.c
  grid/cpu/grid_collocate_dgemm.c
  grid/cpu/grid_context_cpu.c
  grid/cpu/grid_integrate_dgemm.c
  grid/cpu/grid_prepare_pab_dgemm.c
  grid/cpu/non_orthorombic_corrections.c
  grid/cpu/tensor_local.c
  grid/cpu/utils.c
  grid/grid_task_list.c
  grid/ref/grid_ref_collocate.c
  grid/ref/grid_ref_integrate.c
  grid/ref/grid_ref_prepare_pab.c
  grid/ref/grid_ref_task_list.c)

list(APPEND OFFLOAD_SRCS_C offload/offload_buffer.c offload/offload_library.c)

list(APPEND CP2K_SRCS_C pw/fpga/fft_fpga.c pw/fpga/opencl_utils.c)

if(CP2K_USE_LIBTORCH)
  list(APPEND CP2K_SRCS_CPP torch_c_api.cpp)
endif()

if(CP2K_USE_CUDA OR CP2K_USE_HIP)
  if(NOT CP2K_DISABLE_PW_GPU)
    list(APPEND PW_SRCS_GPU pw/gpu/pw_gpu_kernels.cu)
    list(APPEND CP2K_SRCS_C pw/gpu/pw_gpu_internal.c)
  endif()

  if(NOT CP2K_DISABLE_DBM_GPU)
    list(APPEND DBM_SRCS_C dbm/dbm_multiply_gpu.c)
    list(APPEND DBM_SRCS_GPU dbm/dbm_multiply_gpu_kernel.cu)
  endif()

  if(NOT CP2K_DISABLE_GRID_GPU)
    if(CP2K_USE_CUDA)
      list(APPEND GRID_SRCS_GPU grid/gpu/grid_gpu_collocate.cu
           grid/gpu/grid_gpu_integrate.cu grid/gpu/grid_gpu_task_list.cu)
    elseif(CP2K_USE_HIP)
      list(
        APPEND
        GRID_SRCS_GPU
        grid/gpu/grid_gpu_collocate.cu
        grid/gpu/grid_gpu_integrate.cu
        grid/gpu/grid_gpu_task_list.cu
        grid/hip/grid_hip_collocate.cu
        grid/hip/grid_hip_integrate.cu
        grid/hip/grid_hip_context.cu)
    endif()
  endif()
  list(APPEND CP2K_SRCS_GPU ${GRID_SRCS_GPU} ${DBM_SRCS_GPU} ${PW_SRCS_GPU})
endif()

# starting list to compile cp2k without any additional features.
list(APPEND CP2K_SRCS_C ${DBM_SRCS_C} ${GRID_SRCS_C} ${OFFLOAD_SRCS_C})

add_fypp_sources(CP2K_SRCS ${CP2K_SRCS_F})

# set the __SHORT_FILE__ per file for CP2K sources
foreach(cp2k_src ${CP2K_SRCS})
  # add_fypp_sources returns a path in the current binary dir
  get_filename_component(short_file "${cp2k_src}" NAME)
  set_source_files_properties(
    ${cp2k_src} PROPERTIES COMPILE_DEFINITIONS __SHORT_FILE__="${short_file}")
endforeach()

add_library(cp2k "${CP2K_SRCS};${CP2K_SRCS_C};${CP2K_SRCS_GPU}")

target_compile_features(cp2k PUBLIC cxx_std_11)
target_compile_features(cp2k PUBLIC c_std_99)
target_compile_features(cp2k PUBLIC cuda_std_11)

# =================================================================================================
# main CP2K OBJECT LIBRARY
if(CP2K_USE_ACCEL MATCHES "CUDA")
  set_property(TARGET cp2k PROPERTY CUDA_ARCHITECTURES ${CP2K_ACC_ARCH_NUMBER})
  target_compile_definitions(
    cp2k PUBLIC __OFFLOAD_CUDA $<$<COMPILE_LANGUAGE:CUDA>:__OFFLOAD_CUDA>)
  include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
elseif(CP2K_USE_ACCEL MATCHES "HIP")
  set_property(TARGET cp2k PROPERTY HIP_ARCHITECTURES ${CP2K_ACC_ARCH_NUMBER})
endif()

add_library(cp2k_link_libs INTERFACE)
target_link_libraries(
  cp2k_link_libs
  INTERFACE
    $<$<BOOL:${CP2K_USE_PEXSI}>:PEXSI::pexsi>
    $<$<BOOL:${CP2K_USE_SIRIUS}>:sirius::sirius>
    $<$<BOOL:${CP2K_USE_VORI}>:CP2K_VORI::vori>
    $<$<BOOL:${CP2K_USE_PEXSI}>:CP2K_PEXSI::pexsi>
    $<$<BOOL:${CP2K_USE_PEXSI}>:CP2K_ptscotch::ptscotch>
    $<$<BOOL:${CP2K_USE_SPGLIB}>:CP2K_LIBSPG::libspg>
    $<$<BOOL:${CP2K_USE_LIBXC}>:CP2K_Libxc::xc>
    $<$<BOOL:${CP2K_USE_ELPA}>:CP2K_ELPA::elpa>
    $<$<BOOL:${CP2K_USE_FFTW3}>:CP2K_FFTW3::fftw3>
    $<$<BOOL:${CP2K_ENABLE_FFTW3_THREADS_SUPPORT}>:CP2K_FFTW3::fftw3_threads>
    $<$<BOOL:${CP2K_ENABLE_FFTW3_OPENMP_SUPPORT}>:CP2K_FFTW3::fftw3_omp>
    $<$<BOOL:${CP2K_USE_SPLA}>:SPLA::spla>
    $<$<BOOL:${CP2K_USE_LIBINT2}>:CP2K_Libint2::int2>
    $<$<BOOL:${CP2K_USE_COSMA}>:cosma::cosma_prefixed_pxgemm>
    $<$<BOOL:${CP2K_USE_COSMA}>:cosma::cosma>
    $<$<BOOL:${CP2K_USE_COSMA}>:costa::costa>
    DBCSR::dbcsr
    $<$<BOOL:${CP2K_USE_TORCH}>:${TORCH_LIBRARIES}>
    $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cufft>
    $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cufftw>
    $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cublas>
    $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cudart>
    $<$<BOOL:${CP2K_USE_HIP}>:hip::hipfft>
    $<$<BOOL:${CP2K_USE_HIP}>:roc::hipblas>
    $<$<BOOL:${CP2K_USE_HIP}>:hip::device>
    CP2K_SCALAPACK::scalapack
    $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmmf>
    $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmmext>
    $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmm>
    CP2K_LAPACK::lapack
    CP2K_BLAS::blas
    MPI::MPI_Fortran
    MPI::MPI_C
    MPI::MPI_CXX
    OpenMP::OpenMP_Fortran
    OpenMP::OpenMP_C
    OpenMP::OpenMP_CXX)

# mix the target and variables pointing to the include directories.

include_directories(
  ${CMAKE_MPI_INCLUDE_DIRECTORIES}
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/base>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/common>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dbcsrx>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/motion>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/grid>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dbm>)

if(DEFINED ENV{CPATH})
  string(REPLACE ":" ";" INCLUDE_LIST $ENV{CPATH})
  include_directories(${INCLUDE_LIST})
endif()

string(TIMESTAMP CP2K_TIMESTAMP "%Y-%m-%d %H:%M:%S")

target_link_libraries(cp2k PUBLIC cp2k_link_libs)
target_compile_definitions(
  cp2k
  PUBLIC __parallel
         __SCALAPACK
         __COMPILE_DATE=\"${CP2K_TIMESTAMP}\"
         __COMPILE_HOST=\"${CP2K_HOST_NAME}\"
         __COMPILE_REVISION=\"${CP2K_GIT_HASH}\"
         __DATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}/cp2k/data\"
         __COMPILE_ARCH=\"${CMAKE_SYSTEM_PROCESSOR}\"
         $<$<CONFIG:Release>:NDEBUG>
         $<$<BOOL:${CP2K_USE_PEXSI}>:__PEXSI>
         $<$<BOOL:${CP2K_USE_PLUMED2}>:__PLUMED2>
         $<$<BOOL:${CP2K_USE_QUIP}>:__QUIP>
         $<$<BOOL:${CP2K_USE_MAXWELL}>:__LIBMAXWELL>
         $<$<BOOL:${CP2K_USE_VORI}>:__LIBVORI>
         $<$<BOOL:${CP2K_USE_SPGLIB}>:__SPGLIB>
         $<$<BOOL:${CP2K_USE_SIRIUS}>:__SIRIUS>
         $<$<BOOL:${CP2K_USE_SPLA}>:__SPLA>
         $<$<BOOL:${CP2K_USE_SpFFT}>:__SPFFT>
         $<$<BOOL:${CP2K_USE_SPLA_GEMM_OFFLOADING}>:__OFFLOAD_GEMM>
         $<$<BOOL:${CP2K_USE_ELPA}>:__ELPA>
         $<$<BOOL:${CP2K_USE_LIBXC}>:__LIBXC>
         $<$<BOOL:${CP2K_USE_FFTW3}>:__FFTW3>
         $<$<BOOL:${CP2K_USE_LIBINT2}>:__LIBINT>
         $<$<BOOL:${CP2K_USE_PEXSI}>:__LIBPEXSI>
         $<$<BOOL:${CP2K_USE_LIBTORCH}>:__LIBTORCH>
         $<$<BOOL:${CP2K_USE_COSMA}>:__COSMA>
         $<$<BOOL:${CP2K_USE_LIBXSMM}>:__LIBXSMM>
         $<$<STREQUAL:${CP2K_BLAS_VENDOR},MKL>:__MKL>
         $<$<STREQUAL:${CP2K_BLAS_VENDOR},Apple>:__ACCELERATE>
         $<$<BOOL:${CP2K_USE_CUDA}>:__OFFLOAD_CUDA>
         $<$<COMPILE_LANGUAGE:CUDA>:__OFFLOAD_CUDA>
         $<$<BOOL:${CP2K_USE_HIP}>:__OFFLOAD_HIP>
         $<$<BOOL:${CP2K_USE_HIP}>:__HIP_PLATFORM_AMD__>
         $<$<COMPILE_LANGUAGE:HIP>:__OFFLOAD_HIP>
         $<$<COMPILE_LANGUAGE:HIP>:__HIP_PLATFORM_AMD__>)

if(CP2K_USE_CUDA OR CP2K_USE_HIP)
  # these checks are only relevant when the debug mode is on

  if(NOT CP2K_DBCSR_USE_CPU_ONLY)
    target_compile_definitions(cp2k PUBLIC __DBCSR_ACC)
  endif()

  # the next three are off by default
  if(CP2K_DISABLE_GRID_GPU)
    target_compile_definitions(cp2k PUBLIC __NO_OFFLOAD_GRID)
  endif()

  if(CP2K_DISABLE_PW_GPU)
    target_compile_definitions(cp2k PUBLIC __NO_OFFLOAD_PW)
  endif()

  if(CP2K_DISABLE_DBM_GPU)
    target_compile_definitions(cp2k PUBLIC __NO_OFFLOAD_DBM)
  endif()
endif()

if(CP2K_USE_HIP)
  foreach(__src ${CP2K_SRCS_GPU})
    set_source_files_properties(${__src} PROPERTIES LANGUAGE HIP)
  endforeach()
  set_target_properties(cp2k PROPERTIES HIP_ARCHITECTURES
                                        "${CP2K_ACC_ARCH_NUMBER}")
endif()

list(
  APPEND
  __CP2K_APPS
  "memory_utilities_unittest"
  "parallel_rng_types_unittest"
  "graph"
  "dumpdcd"
  "xyz2dcd"
  "libcp2k_unittest")

add_executable(cp2k-bin start/cp2k.F)
set_target_properties(
  cp2k-bin PROPERTIES LINKER_LANGUAGE Fortran) # always use the Fortran compiler
                                               # for
# linking

add_executable(memory_utilities_unittest common/memory_utilities_unittest.F)
add_executable(parallel_rng_types_unittest common/parallel_rng_types_unittest.F)
add_executable(graph metadyn_tools/graph.F)
add_executable(dumpdcd motion/dumpdcd.F)
add_executable(xyz2dcd motion/xyz2dcd.F)
add_executable(libcp2k_unittest start/libcp2k_unittest.c)

set_target_properties(cp2k-bin PROPERTIES CXX_STANDARD 11)
set_target_properties(cp2k-bin PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES
                                          "CXX")
set_target_properties(cp2k-bin PROPERTIES LINKER_LANGUAGE Fortran)
set_target_properties(cp2k-bin PROPERTIES OUTPUT_NAME cp2k)
target_link_libraries(cp2k-bin PUBLIC cp2k)

foreach(_app ${__CP2K_APPS})
  set_target_properties(${_app} PROPERTIES LINKER_LANGUAGE Fortran)
  set_target_properties(${_app} PROPERTIES CXX_STANDARD 11)
  set_target_properties(${_app} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES
                                           "CXX")
  target_compile_features(${_app} PUBLIC c_std_99)
  if(CP2K_USE_ACCEL MATCHES HIP)
    set_target_properties(${_app} PROPERTIES HIP_ARCHITECTURES
                                             ${CP2K_ACC_ARCH_NUMBER})
  endif()
  target_link_libraries(${_app} PUBLIC cp2k)
endforeach()

#
# apps included in the grid module
#

list(APPEND __GRID_APPS "grid_miniapp" "grid_unittest")

add_executable(
  grid_miniapp
  "grid/grid_miniapp.c;grid/grid_replay.c;${GRID_SRCS_C};${OFFLOAD_SRCS_C};${GRID_SRCS_GPU}"
)
add_executable(
  grid_unittest
  "grid/grid_unittest.c;grid/grid_replay.c;${GRID_SRCS_C};${OFFLOAD_SRCS_C};${GRID_SRCS_GPU}"
)

foreach(_app ${__GRID_APPS})
  set_target_properties(${_app} PROPERTIES LINKER_LANGUAGE C)
  target_compile_features(${_app} PUBLIC c_std_99)

  target_link_libraries(
    ${_app}
    PUBLIC $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cudart>
           $<$<BOOL:${CP2K_USE_HIP}>:hip::device>
           $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmmf>
           $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmm>
           CP2K_BLAS::blas
           OpenMP::OpenMP_C
           m)

  target_include_directories(
    ${_app} PUBLIC $<$<BOOL:${CP2K_USE_CUDA}>:${CMAKE_CUDA_INCLUDE_DIRECTORIES}>
                   $<$<BOOL:${CP2K_USE_HIP}>:${CMAKE_HIP_INCLUDE_DIRECTORIES}>)

  target_compile_definitions(
    ${_app}
    PUBLIC $<$<BOOL:${CP2K_USE_CUDA}>:__OFFLOAD_CUDA>
           $<$<BOOL:${CP2K_USE_HIP}>:__OFFLOAD_HIP>
           $<$<STREQUAL:CP2K_BLAS_VENDOR,"MKL">:__MKL>
           $<$<BOOL:${CP2K_USE_LIBXSMM}>:__LIBXSMM>)

  target_compile_features(${_app} PUBLIC $<$<BOOL:CP2K_USE_CUDA>:cuda_std_11>)

  if(CP2K_USE_CUDA)
    set_target_properties(${_app} PROPERTIES CUDA_ARCHITECTURES
                                             ${CP2K_ACC_ARCH_NUMBER})
  endif()

  # cmake 3.21 is needed for this
  if(CP2K_USE_HIP)
    set_target_properties(${_app} PROPERTIES HIP_ARCHITECTURES
                                             ${CP2K_ACC_ARCH_NUMBER})
  endif()
endforeach()

#
# apps included in dbm
#

add_executable(dbm_miniapp dbm/dbm_miniapp.c ${DBM_SRCS_C} ${OFFLOAD_SRCS_C}
                           ${DBM_SRCS_GPU})
target_compile_features(dbm_miniapp PUBLIC c_std_99)

set_target_properties(dbm_miniapp PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(
  dbm_miniapp
  PUBLIC $<$<BOOL:${CP2K_USE_CUDA}>:CUDA::cudart>
         $<$<BOOL:${CP2K_USE_HIP}>:hip::device>
         $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmmf>
         $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmmext>
         $<$<BOOL:${CP2K_USE_LIBXSMM}>:CP2K_LibXSMM::libxsmm>
         MPI::MPI_C
         CP2K_BLAS::blas
         OpenMP::OpenMP_C
         m)

target_compile_definitions(
  dbm_miniapp
  PUBLIC $<$<BOOL:${CP2K_USE_CUDA}>:__OFFLOAD_CUDA>
         $<$<BOOL:${CP2K_USE_HIP}>:__OFFLOAD_HIP>
         $<$<BOOL:${CP2K_USE_LIBXSMM}>:__LIBXSMM>)

if(CP2K_DISABLE_DBM_GPU)
  if(CP2K_USE_CUDA)
    target_compile_features(dbm_miniapp PUBLIC cuda_std_11)
    set_target_properties(dbm_miniapp PROPERTIES CUDA_ARCHITECTURES
                                                 ${CP2K_ACC_ARCH_NUMBER})
  endif()

  # cmake 3.21 is needed for this
  if(CP2K_USE_HIP)
    set_target_properties(dbm_miniapp PROPERTIES HIP_ARCHITECTURES
                                                 ${CP2K_ACC_ARCH_NUMBER})
  endif()
endif()

# installation

foreach(_app ${__GRID_APPS} ${__CP2K_APPS} cp2k-bin)
  install(
    TARGETS ${_app}
    RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
    LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
    INCLUDES
    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cp2k")
endforeach()

install(DIRECTORY "${CMAKE_SOURCE_DIR}/data"
        DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/cp2k")
install(TARGETS cp2k LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
