xref: /aosp_15_r20/external/llvm/cmake/modules/AddOCaml.cmake (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker# CMake build rules for the OCaml language.
2*9880d681SAndroid Build Coastguard Worker# Assumes FindOCaml is used.
3*9880d681SAndroid Build Coastguard Worker# http://ocaml.org/
4*9880d681SAndroid Build Coastguard Worker#
5*9880d681SAndroid Build Coastguard Worker# Example usage:
6*9880d681SAndroid Build Coastguard Worker#
7*9880d681SAndroid Build Coastguard Worker# add_ocaml_library(pkg_a OCAML mod_a OCAMLDEP pkg_b C mod_a_stubs PKG ctypes LLVM core)
8*9880d681SAndroid Build Coastguard Worker#
9*9880d681SAndroid Build Coastguard Worker# Unnamed parameters:
10*9880d681SAndroid Build Coastguard Worker#
11*9880d681SAndroid Build Coastguard Worker#   * Library name.
12*9880d681SAndroid Build Coastguard Worker#
13*9880d681SAndroid Build Coastguard Worker# Named parameters:
14*9880d681SAndroid Build Coastguard Worker#
15*9880d681SAndroid Build Coastguard Worker# OCAML     OCaml module names. Imply presence of a corresponding .ml and .mli files.
16*9880d681SAndroid Build Coastguard Worker# OCAMLDEP  Names of libraries this library depends on.
17*9880d681SAndroid Build Coastguard Worker# C         C stub sources. Imply presence of a corresponding .c file.
18*9880d681SAndroid Build Coastguard Worker# CFLAGS    Additional arguments passed when compiling C stubs.
19*9880d681SAndroid Build Coastguard Worker# PKG       Names of ocamlfind packages this library depends on.
20*9880d681SAndroid Build Coastguard Worker# LLVM      Names of LLVM libraries this library depends on.
21*9880d681SAndroid Build Coastguard Worker# NOCOPY    Do not automatically copy sources (.c, .ml, .mli) from the source directory,
22*9880d681SAndroid Build Coastguard Worker#           e.g. if they are generated.
23*9880d681SAndroid Build Coastguard Worker#
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Workerfunction(add_ocaml_library name)
26*9880d681SAndroid Build Coastguard Worker  CMAKE_PARSE_ARGUMENTS(ARG "NOCOPY" "" "OCAML;OCAMLDEP;C;CFLAGS;PKG;LLVM" ${ARGN})
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker  set(src ${CMAKE_CURRENT_SOURCE_DIR})
29*9880d681SAndroid Build Coastguard Worker  set(bin ${CMAKE_CURRENT_BINARY_DIR})
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker  set(ocaml_pkgs)
32*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_pkg ${ARG_PKG} )
33*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_pkgs "-package" "${ocaml_pkg}")
34*9880d681SAndroid Build Coastguard Worker  endforeach()
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker  set(sources)
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker  set(ocaml_inputs)
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker  set(ocaml_outputs "${bin}/${name}.cma")
41*9880d681SAndroid Build Coastguard Worker  if( ARG_C )
42*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_outputs
43*9880d681SAndroid Build Coastguard Worker         "${bin}/lib${name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
44*9880d681SAndroid Build Coastguard Worker    if ( BUILD_SHARED_LIBS )
45*9880d681SAndroid Build Coastguard Worker      list(APPEND ocaml_outputs
46*9880d681SAndroid Build Coastguard Worker           "${bin}/dll${name}${CMAKE_SHARED_LIBRARY_SUFFIX}")
47*9880d681SAndroid Build Coastguard Worker    endif()
48*9880d681SAndroid Build Coastguard Worker  endif()
49*9880d681SAndroid Build Coastguard Worker  if( HAVE_OCAMLOPT )
50*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_outputs
51*9880d681SAndroid Build Coastguard Worker         "${bin}/${name}.cmxa"
52*9880d681SAndroid Build Coastguard Worker         "${bin}/${name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
53*9880d681SAndroid Build Coastguard Worker  endif()
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker  set(ocaml_flags "-lstdc++" "-ldopt" "-L${LLVM_LIBRARY_DIR}"
56*9880d681SAndroid Build Coastguard Worker                  "-ccopt" "-L\\$CAMLORIGIN/.."
57*9880d681SAndroid Build Coastguard Worker                  "-ccopt" "-Wl,-rpath,\\$CAMLORIGIN/.."
58*9880d681SAndroid Build Coastguard Worker                  ${ocaml_pkgs})
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_dep ${ARG_OCAMLDEP} )
61*9880d681SAndroid Build Coastguard Worker    get_target_property(dep_ocaml_flags "ocaml_${ocaml_dep}" OCAML_FLAGS)
62*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_flags ${dep_ocaml_flags})
63*9880d681SAndroid Build Coastguard Worker  endforeach()
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker  if( NOT BUILD_SHARED_LIBS )
66*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_flags "-custom")
67*9880d681SAndroid Build Coastguard Worker  endif()
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker  explicit_map_components_to_libraries(llvm_libs ${ARG_LLVM})
70*9880d681SAndroid Build Coastguard Worker  foreach( llvm_lib ${llvm_libs} )
71*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_flags "-l${llvm_lib}" )
72*9880d681SAndroid Build Coastguard Worker  endforeach()
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker  get_property(system_libs TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS)
75*9880d681SAndroid Build Coastguard Worker  foreach(system_lib ${system_libs})
76*9880d681SAndroid Build Coastguard Worker    if (system_lib MATCHES "^-")
77*9880d681SAndroid Build Coastguard Worker      # If it's an option, pass it without changes.
78*9880d681SAndroid Build Coastguard Worker      list(APPEND ocaml_flags "${system_lib}" )
79*9880d681SAndroid Build Coastguard Worker    else()
80*9880d681SAndroid Build Coastguard Worker      # Otherwise assume it's a library name we need to link with.
81*9880d681SAndroid Build Coastguard Worker      list(APPEND ocaml_flags "-l${system_lib}" )
82*9880d681SAndroid Build Coastguard Worker    endif()
83*9880d681SAndroid Build Coastguard Worker  endforeach()
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker  string(REPLACE ";" " " ARG_CFLAGS "${ARG_CFLAGS}")
86*9880d681SAndroid Build Coastguard Worker  set(c_flags "${ARG_CFLAGS} ${LLVM_DEFINITIONS}")
87*9880d681SAndroid Build Coastguard Worker  foreach( include_dir ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR} )
88*9880d681SAndroid Build Coastguard Worker    set(c_flags "${c_flags} -I${include_dir}")
89*9880d681SAndroid Build Coastguard Worker  endforeach()
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_file ${ARG_OCAML} )
92*9880d681SAndroid Build Coastguard Worker    list(APPEND sources "${ocaml_file}.mli" "${ocaml_file}.ml")
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_inputs "${bin}/${ocaml_file}.mli" "${bin}/${ocaml_file}.ml")
95*9880d681SAndroid Build Coastguard Worker
96*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_outputs "${bin}/${ocaml_file}.cmi" "${bin}/${ocaml_file}.cmo")
97*9880d681SAndroid Build Coastguard Worker    if( HAVE_OCAMLOPT )
98*9880d681SAndroid Build Coastguard Worker      list(APPEND ocaml_outputs
99*9880d681SAndroid Build Coastguard Worker           "${bin}/${ocaml_file}.cmx"
100*9880d681SAndroid Build Coastguard Worker           "${bin}/${ocaml_file}${CMAKE_C_OUTPUT_EXTENSION}")
101*9880d681SAndroid Build Coastguard Worker    endif()
102*9880d681SAndroid Build Coastguard Worker  endforeach()
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker  foreach( c_file ${ARG_C} )
105*9880d681SAndroid Build Coastguard Worker    list(APPEND sources "${c_file}.c")
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker    list(APPEND c_inputs  "${bin}/${c_file}.c")
108*9880d681SAndroid Build Coastguard Worker    list(APPEND c_outputs "${bin}/${c_file}${CMAKE_C_OUTPUT_EXTENSION}")
109*9880d681SAndroid Build Coastguard Worker  endforeach()
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker  if( NOT ARG_NOCOPY )
112*9880d681SAndroid Build Coastguard Worker    foreach( source ${sources} )
113*9880d681SAndroid Build Coastguard Worker      add_custom_command(
114*9880d681SAndroid Build Coastguard Worker          OUTPUT "${bin}/${source}"
115*9880d681SAndroid Build Coastguard Worker          COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${src}/${source}" "${bin}"
116*9880d681SAndroid Build Coastguard Worker          DEPENDS "${src}/${source}"
117*9880d681SAndroid Build Coastguard Worker          COMMENT "Copying ${source} to build area")
118*9880d681SAndroid Build Coastguard Worker    endforeach()
119*9880d681SAndroid Build Coastguard Worker  endif()
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker  foreach( c_input ${c_inputs} )
122*9880d681SAndroid Build Coastguard Worker    get_filename_component(basename "${c_input}" NAME_WE)
123*9880d681SAndroid Build Coastguard Worker    add_custom_command(
124*9880d681SAndroid Build Coastguard Worker      OUTPUT "${basename}${CMAKE_C_OUTPUT_EXTENSION}"
125*9880d681SAndroid Build Coastguard Worker      COMMAND "${OCAMLFIND}" "ocamlc" "-c" "${c_input}" -ccopt ${c_flags}
126*9880d681SAndroid Build Coastguard Worker      DEPENDS "${c_input}"
127*9880d681SAndroid Build Coastguard Worker      COMMENT "Building OCaml stub object file ${basename}${CMAKE_C_OUTPUT_EXTENSION}"
128*9880d681SAndroid Build Coastguard Worker      VERBATIM)
129*9880d681SAndroid Build Coastguard Worker  endforeach()
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker  set(ocaml_params)
132*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_input ${ocaml_inputs} ${c_outputs})
133*9880d681SAndroid Build Coastguard Worker    get_filename_component(filename "${ocaml_input}" NAME)
134*9880d681SAndroid Build Coastguard Worker    list(APPEND ocaml_params "${filename}")
135*9880d681SAndroid Build Coastguard Worker  endforeach()
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker  if( APPLE )
138*9880d681SAndroid Build Coastguard Worker    set(ocaml_rpath "@executable_path/../../lib")
139*9880d681SAndroid Build Coastguard Worker  elseif( UNIX )
140*9880d681SAndroid Build Coastguard Worker    set(ocaml_rpath "\\$ORIGIN/../../lib")
141*9880d681SAndroid Build Coastguard Worker  endif()
142*9880d681SAndroid Build Coastguard Worker  list(APPEND ocaml_flags "-ldopt" "-Wl,-rpath,${ocaml_rpath}")
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker  add_custom_command(
145*9880d681SAndroid Build Coastguard Worker    OUTPUT ${ocaml_outputs}
146*9880d681SAndroid Build Coastguard Worker    COMMAND "${OCAMLFIND}" "ocamlmklib" "-o" "${name}" ${ocaml_flags} ${ocaml_params}
147*9880d681SAndroid Build Coastguard Worker    DEPENDS ${ocaml_inputs} ${c_outputs}
148*9880d681SAndroid Build Coastguard Worker    COMMENT "Building OCaml library ${name}"
149*9880d681SAndroid Build Coastguard Worker    VERBATIM)
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker  add_custom_command(
152*9880d681SAndroid Build Coastguard Worker    OUTPUT "${bin}/${name}.odoc"
153*9880d681SAndroid Build Coastguard Worker    COMMAND "${OCAMLFIND}" "ocamldoc"
154*9880d681SAndroid Build Coastguard Worker            "-I" "${bin}"
155*9880d681SAndroid Build Coastguard Worker            "-I" "${LLVM_LIBRARY_DIR}/ocaml/"
156*9880d681SAndroid Build Coastguard Worker            "-dump" "${bin}/${name}.odoc"
157*9880d681SAndroid Build Coastguard Worker            ${ocaml_pkgs} ${ocaml_inputs}
158*9880d681SAndroid Build Coastguard Worker    DEPENDS ${ocaml_inputs} ${ocaml_outputs}
159*9880d681SAndroid Build Coastguard Worker    COMMENT "Building OCaml documentation for ${name}"
160*9880d681SAndroid Build Coastguard Worker    VERBATIM)
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker  add_custom_target("ocaml_${name}" ALL DEPENDS ${ocaml_outputs} "${bin}/${name}.odoc")
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker  set_target_properties("ocaml_${name}" PROPERTIES
165*9880d681SAndroid Build Coastguard Worker    OCAML_FLAGS "-I;${bin}")
166*9880d681SAndroid Build Coastguard Worker  set_target_properties("ocaml_${name}" PROPERTIES
167*9880d681SAndroid Build Coastguard Worker    OCAML_ODOC "${bin}/${name}.odoc")
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_dep ${ARG_OCAMLDEP} )
170*9880d681SAndroid Build Coastguard Worker    add_dependencies("ocaml_${name}" "ocaml_${ocaml_dep}")
171*9880d681SAndroid Build Coastguard Worker  endforeach()
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker  foreach( llvm_lib ${llvm_libs} )
174*9880d681SAndroid Build Coastguard Worker    add_dependencies("ocaml_${name}" "${llvm_lib}")
175*9880d681SAndroid Build Coastguard Worker  endforeach()
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker  set(install_files)
178*9880d681SAndroid Build Coastguard Worker  set(install_shlibs)
179*9880d681SAndroid Build Coastguard Worker  foreach( ocaml_output ${ocaml_outputs} )
180*9880d681SAndroid Build Coastguard Worker    get_filename_component(ext "${ocaml_output}" EXT)
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker    if( NOT (ext STREQUAL ".cmo" OR
183*9880d681SAndroid Build Coastguard Worker             ext STREQUAL CMAKE_C_OUTPUT_EXTENSION OR
184*9880d681SAndroid Build Coastguard Worker             ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX) )
185*9880d681SAndroid Build Coastguard Worker      list(APPEND install_files "${ocaml_output}")
186*9880d681SAndroid Build Coastguard Worker    elseif( ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX)
187*9880d681SAndroid Build Coastguard Worker      list(APPEND install_shlibs "${ocaml_output}")
188*9880d681SAndroid Build Coastguard Worker    endif()
189*9880d681SAndroid Build Coastguard Worker  endforeach()
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker  install(FILES ${install_files}
192*9880d681SAndroid Build Coastguard Worker          DESTINATION lib/ocaml)
193*9880d681SAndroid Build Coastguard Worker  install(FILES ${install_shlibs}
194*9880d681SAndroid Build Coastguard Worker          PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
195*9880d681SAndroid Build Coastguard Worker                      GROUP_READ GROUP_EXECUTE
196*9880d681SAndroid Build Coastguard Worker                      WORLD_READ WORLD_EXECUTE
197*9880d681SAndroid Build Coastguard Worker          DESTINATION lib/ocaml)
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker  foreach( install_file ${install_files} ${install_shlibs} )
200*9880d681SAndroid Build Coastguard Worker    get_filename_component(filename "${install_file}" NAME)
201*9880d681SAndroid Build Coastguard Worker    add_custom_command(TARGET "ocaml_${name}" POST_BUILD
202*9880d681SAndroid Build Coastguard Worker      COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${install_file}"
203*9880d681SAndroid Build Coastguard Worker                                             "${LLVM_LIBRARY_DIR}/ocaml/"
204*9880d681SAndroid Build Coastguard Worker      COMMENT "Copying OCaml library component ${filename} to intermediate area"
205*9880d681SAndroid Build Coastguard Worker      VERBATIM)
206*9880d681SAndroid Build Coastguard Worker  endforeach()
207*9880d681SAndroid Build Coastguard Workerendfunction()
208