1# Load Conan
2
3if( ${_OPT}conan_enabled )
4    include( conan )
5
6    conan_add_remote(NAME audacity
7        URL https://artifactory.audacityteam.org/artifactory/api/conan/conan-local
8        VERIFY_SSL True
9    )
10endif()
11
12if ( ${_OPT}conan_allow_prebuilt_binaries )
13    set ( CONAN_BUILD_MODE BUILD missing )
14else()
15    set( CONAN_BUILD_MODE BUILD all )
16endif()
17
18set( CONAN_BUILD_REQUIRES )
19set( CONAN_REQUIRES )
20set( CONAN_PACKAGE_OPTIONS )
21set( CONAN_ONLY_DEBUG_RELEASE )
22set( CONAN_CONFIG_OPTIONS )
23set( CONAN_RESOLVE_LIST )
24
25#[[
26Add a Conan dependency
27
28Example usage:
29
30add_conan_lib(
31  wxWdidget
32  wxwidgets/3.1.3-audacity
33  OPTION_NAME wxwidgets
34  SYMBOL WXWIDGET
35  REQUIRED
36  ALWAYS_ALLOW_CONAN_FALLBACK
37  PKG_CONFIG "wxwidgets >= 3.1.3"
38  FIND_PACKAGE_OPTIONS COMPONENTS adv base core html qa xml
39  INTERFACE_NAME wxwidgets::wxwidgets
40  HAS_ONLY_DEBUG_RELEASE
41  CONAN_OPTIONS
42       wxwidgets:shared=True
43)
44
45PKG_CONFIG accepts a list of possible package configurations.
46add_conan_lib will iterate over it one by one until the library is found.
47]]
48
49function (add_conan_lib package conan_package_name )
50    # Extract the list of packages from the function args
51    list( SUBLIST ARGV 2 -1 options )
52
53    set( list_mode on )
54    set( current_var "conan_package_options" )
55
56    set( option_name_base ${package} )
57    set( allow_find_package off )
58    set( find_package_options )
59    set( conan_package_options )
60    set( required off )
61    set( pkg_config_options )
62    set( system_only ${${_OPT}obey_system_dependencies})
63    set( interface_name "${package}::${package}")
64
65    # Parse function arguments
66
67    foreach( opt IN LISTS options )
68        if( opt STREQUAL "FIND_PACKAGE_OPTIONS" )
69            set( list_mode on )
70            set( allow_find_package on )
71            set( current_var "find_package_options" )
72        elseif ( opt STREQUAL "ALLOW_FIND_PACKAGE" )
73            set ( allow_find_package on )
74        elseif ( opt STREQUAL "CONAN_OPTIONS" )
75            set( list_mode on )
76            set( current_var "conan_package_options" )
77        elseif ( opt STREQUAL "PKG_CONFIG" )
78            set( list_mode on )
79            set( current_var "pkg_config_options" )
80        elseif ( opt STREQUAL "OPTION_NAME" )
81            set( list_mode off )
82            set( current_var "option_name_base" )
83        elseif ( opt STREQUAL "SYMBOL" )
84            set( list_mode off )
85            set( current_var "symbol" )
86        elseif ( opt STREQUAL "INTERFACE_NAME" )
87            set( list_mode off )
88            set( current_var "interface_name" )
89        elseif ( opt STREQUAL "REQUIRED" )
90            set( required on )
91        elseif ( opt STREQUAL "ALWAYS_ALLOW_CONAN_FALLBACK" )
92            set( system_only off )
93        elseif ( opt STREQUAL "HAS_ONLY_DEBUG_RELEASE" )
94            set ( only_debug_release on )
95        else()
96            if( list_mode )
97                list( APPEND ${current_var} ${opt} )
98            else()
99                set (${current_var} ${opt})
100            endif()
101        endif()
102    endforeach()
103
104    if( NOT DEFINED symbol )
105        string( TOUPPER "${option_name_base}" symbol)
106    endif()
107
108    # Generate CMake option
109    set( option_name ${_OPT}use_${option_name_base} )
110
111    set( option_desc "local" )
112
113    if( pkg_config_options OR allow_find_package OR NOT ${_OPT}conan_enabled )
114        set( sysopt "system" )
115        string( PREPEND option_desc "system (if available), " )
116
117        if( ${_OPT}conan_enabled )
118            set( default "${${_OPT}lib_preference}" )
119        else()
120            set( default "system" )
121        endif()
122    else()
123        set( default "local" )
124    endif()
125
126    if( ${_OPT}conan_enabled )
127        set( localopt "local" )
128    endif()
129
130    if( NOT required )
131        set( reqopt "off" )
132        string( APPEND option_desc ", off" )
133    endif()
134
135    cmd_option( ${option_name}
136                "Use ${option_name_base} library [${option_desc}]"
137                "${default}"
138                STRINGS ${sysopt} ${localopt} ${reqopt}
139    )
140
141    # Early bail out
142    if( ${option_name} STREQUAL "off" )
143
144      message( STATUS "========== ${option_name_base} disabled ==========" )
145
146      set( USE_${symbol} OFF CACHE INTERNAL "" FORCE )
147
148      return()
149    endif()
150
151    # Let the Audacity target know that this library will be used
152    set( USE_${symbol} ON CACHE INTERNAL "" FORCE )
153
154    if ( TARGET "${package}" )
155        return()
156    endif()
157
158    if( ${option_name} STREQUAL "system" OR NOT ${_OPT}conan_enabled )
159        if( pkg_config_options )
160            foreach(variant ${pkg_config_options})
161                pkg_check_modules( PKG_${package} ${variant} )
162
163                if( PKG_${package}_FOUND )
164                    message( STATUS "Using '${package}' system library" )
165
166                    # Create the target interface library
167                    add_library( ${interface_name} INTERFACE IMPORTED GLOBAL)
168
169                    # Retrieve the package information
170                    get_package_interface( PKG_${package} ${interface_name} )
171                    return()
172                endif()
173            endforeach()
174        endif()
175
176        if( allow_find_package )
177            find_package( ${package} QUIET ${find_package_options} )
178
179            if ( ${package}_FOUND )
180                message( STATUS "Using '${package}' system library" )
181                return()
182            endif()
183        endif()
184
185        if( system_only OR NOT ${_OPT}conan_enabled )
186            message( FATAL_ERROR "Failed to find the system package ${package}" )
187        else()
188            set( ${option_name} "local" )
189            set_property( CACHE ${option_name} PROPERTY VALUE "local" )
190        endif()
191    endif()
192
193    list( APPEND CONAN_REQUIRES ${conan_package_name} )
194    list( APPEND CONAN_PACKAGE_OPTIONS ${conan_package_options} )
195    list( APPEND CONAN_RESOLVE_LIST ${package} )
196
197    if ( only_debug_release )
198        message( STATUS "${package} only has Debug and Release versions" )
199        list( APPEND CONAN_ONLY_DEBUG_RELEASE ${package})
200    endif()
201
202    set( CONAN_REQUIRES           ${CONAN_REQUIRES}           PARENT_SCOPE )
203    set( CONAN_PACKAGE_OPTIONS    ${CONAN_PACKAGE_OPTIONS}    PARENT_SCOPE )
204    set( CONAN_RESOLVE_LIST       ${CONAN_RESOLVE_LIST}       PARENT_SCOPE )
205    set( CONAN_ONLY_DEBUG_RELEASE ${CONAN_ONLY_DEBUG_RELEASE} PARENT_SCOPE )
206
207    message (STATUS "Adding Conan dependency ${package}")
208endfunction()
209
210macro( set_conan_vars_to_parent )
211    set( CONAN_REQUIRES        ${CONAN_REQUIRES}        PARENT_SCOPE )
212    set( CONAN_PACKAGE_OPTIONS ${CONAN_PACKAGE_OPTIONS} PARENT_SCOPE )
213    set( CONAN_RESOLVE_LIST    ${CONAN_RESOLVE_LIST}    PARENT_SCOPE )
214    set( CONAN_BUILD_REQUIRES  ${CONAN_BUILD_REQUIRES}  PARENT_SCOPE )
215    set( CONAN_ONLY_DEBUG_RELEASE ${CONAN_ONLY_DEBUG_RELEASE} PARENT_SCOPE )
216endmacro()
217
218function ( _conan_install build_type )
219    conan_cmake_configure (
220        REQUIRES ${CONAN_REQUIRES}
221        GENERATORS cmake_find_package_multi
222        BUILD_REQUIRES ${CONAN_BUILD_REQUIRES}
223        ${CONAN_CONFIG_OPTIONS}
224        IMPORTS "bin, *.dll -> ./${_SHARED_PROXY_BASE}/${build_type} @ keep_path=False"
225        IMPORTS "lib, *.dll -> ./${_SHARED_PROXY_BASE}/${build_type} @ keep_path=False"
226        IMPORTS "lib, *.dylib -> ./${_SHARED_PROXY_BASE}/${build_type} @ keep_path=False"
227        IMPORTS "lib, *.so* -> ./${_SHARED_PROXY_BASE}/${build_type} @ keep_path=False"
228        OPTIONS ${CONAN_PACKAGE_OPTIONS}
229    )
230
231    message(STATUS "Configuring packages for ${build_type}")
232
233    conan_cmake_autodetect(settings BUILD_TYPE ${build_type})
234
235    if( CMAKE_SYSTEM_NAME MATCHES "Darwin" )
236        # TODO: Read the target CPU architecture from the CMake option
237        # We have no AppleSilicon support yet
238        list( APPEND settings "arch=x86_64" )
239        list( APPEND settings "os.version=${CMAKE_OSX_DEPLOYMENT_TARGET}" )
240        # This line is required to workaround the conan bug #8025
241        # https://github.com/conan-io/conan/issues/8025
242        # Without it, libjpeg-turbo will fail to cross-compile on AppleSilicon macs
243        list( APPEND settings ENV "CONAN_CMAKE_SYSTEM_PROCESSOR=x86_64")
244    endif()
245
246    if( CMAKE_SYSTEM_NAME MATCHES "DragonFly" )
247        list( APPEND settings "os=FreeBSD" )
248        list( APPEND settings "os_build=FreeBSD" )
249    endif()
250
251    if (build_type MATCHES "MinSizeRel|RelWithDebInfo")
252        message(STATUS "Release only libraries: ${CONAN_ONLY_DEBUG_RELEASE}")
253
254        foreach( package ${CONAN_ONLY_DEBUG_RELEASE} )
255            list( APPEND settings "${package}:build_type=Release")
256        endforeach()
257    endif()
258
259
260    conan_cmake_install(PATH_OR_REFERENCE .
261        ${CONAN_BUILD_MODE}
262        SETTINGS ${settings}
263    )
264endfunction()
265
266macro( resolve_conan_dependencies )
267    if( ${_OPT}conan_enabled )
268        message(STATUS
269        "Executing Conan: \
270            REQUIRES ${CONAN_REQUIRES}
271            GENERATORS cmake_find_package_multi
272            BUILD_REQUIRES ${CONAN_BUILD_REQUIRES}
273            ${CONAN_CONFIG_OPTIONS}
274            OPTIONS ${CONAN_PACKAGE_OPTIONS}
275        ")
276
277        if(MSVC OR XCODE)
278            foreach(TYPE ${CMAKE_CONFIGURATION_TYPES})
279                _conan_install(${TYPE})
280            endforeach()
281        else()
282            _conan_install(${CMAKE_BUILD_TYPE})
283        endif()
284
285        list( REMOVE_DUPLICATES CONAN_REQUIRES )
286
287        foreach( package ${CONAN_RESOLVE_LIST} )
288            message(STATUS "Resolving Conan library ${package}")
289
290            find_package(${package} CONFIG)
291            mark_as_advanced(${package}_DIR)
292
293            if (NOT ${package}_FOUND)
294                message( FATAL_ERROR "Failed to find the conan package ${package}" )
295            endif()
296        endforeach()
297    endif()
298
299    file(GLOB dependency_helpers "${AUDACITY_MODULE_PATH}/dependencies/*.cmake")
300
301    foreach(f ${dependency_helpers})
302        include(${f})
303    endforeach()
304endmacro()
305
306macro ( find_required_package package_name system_package_name )
307    find_package ( ${package_name} QUIET ${ARGN} )
308
309    if ( NOT ${package_name}_FOUND )
310        if (CMAKE_SYSTEM_NAME MATCHES "Darwin|Windows")
311            message( FATAL_ERROR "Error: ${package_name} is required")
312        else()
313            message( FATAL_ERROR "Error: ${package_name} is required.\nPlease install it with using command like:\n\t\$ sudo apt install ${system_package_name}" )
314        endif()
315    endif()
316endmacro()
317