• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018-2020 Peter Dimov
2# Distributed under the Boost Software License, Version 1.0.
3# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
4
5import modules ;
6import boostcpp ;
7import property-set ;
8import "class" : new ;
9import project ;
10import common ;
11import print ;
12import os ;
13import feature ;
14import package ;
15import sequence ;
16import set ;
17import type ;
18import path ;
19import regex ;
20import ./boost-install-dirs ;
21
22feature.feature library-type : : free ;
23feature.feature boost-install.dependency : : free ;
24feature.feature boost-install.cmakedir : : free ;
25feature.feature boost-install.includedir : : free ;
26feature.feature boost-install.libdir : : free ;
27feature.feature boost-install.lib-target-type : : free ;
28
29if "--verbose" in [ modules.peek : ARGV ]
30{
31    .info-enabled = 1 ;
32}
33
34if "--debug-boost-install" in [ modules.peek : ARGV ]
35{
36    .debug-enabled = 1 ;
37}
38
39local rule .info ( messages * )
40{
41    if $(.info-enabled)
42    {
43        ECHO "info:" $(messages) ;
44    }
45}
46
47local rule .debug ( messages * )
48{
49    if $(.debug-enabled)
50    {
51        ECHO "boost-install:" $(messages) ;
52    }
53}
54
55# generate-cmake-variant-
56
57rule generate-cmake-variant- ( target : sources * : properties * )
58{
59    .info generate-cmake-variant- $(target) ":" $(sources) ;
60
61    local ps = [ property-set.create $(properties) ] ;
62
63    print.output $(target) ;
64
65    local version = [ $(ps).get <version> ] ;
66    .info "  version=" $(version) ;
67
68    local name = [ $(ps).get <name> ] ;
69    .info "  name=" $(name) ;
70
71    local variant = [ $(ps).get <variant> ] ;
72    .info "  variant=" $(variant) ;
73
74    local link = [ $(ps).get <link> ] ;
75    .info "  link= " $(link) ;
76
77    local runtime-link = [ $(ps).get <runtime-link> ] ;
78    .info "  runtime-link=" $(runtime-link) ;
79
80    local runtime-debugging = [ $(ps).get <runtime-debugging> ] ;
81    .info "  runtime-debugging=" $(runtime-debugging) ;
82
83    local threading = [ $(ps).get <threading> ] ;
84    .info "  threading=" $(threading) ;
85
86    local address-model = [ $(ps).get <address-model> ] ;
87    .info "  address-model=" $(address-model) ;
88
89    local toolset = [ MATCH ^-(.*) : [ common.format-name <toolset> : "" : "" : $(ps) ] ] ;
90    .info "  toolset=" $(toolset) ;
91
92    local fname = $(sources[1]:BS) ;
93    .info "  fname=" $(fname) ;
94
95    local layout = [ modules.peek boostcpp : layout ] ;
96    .info "  layout=" $(layout) ;
97
98    print.text
99
100        "# Generated by Boost $(version)"
101        ""
102        : true ;
103
104    print.text "# address-model=$(address-model)" "" : true ;
105
106    if $(address-model) = 32
107    {
108        print.text
109
110            "if(CMAKE_SIZEOF_VOID_P EQUAL 8)"
111            "  _BOOST_SKIPPED(\"$(fname)\" \"32 bit, need 64\")"
112            "  return()"
113            "endif()"
114            ""
115            : true ;
116    }
117    else
118    {
119        print.text
120
121            "if(CMAKE_SIZEOF_VOID_P EQUAL 4)"
122            "  _BOOST_SKIPPED(\"$(fname)\" \"64 bit, need 32\")"
123            "  return()"
124            "endif()"
125            ""
126            : true ;
127    }
128
129    local python ;
130
131    local relevant = [ $(ps).get <relevant> ] ;
132    relevant = [ feature.expand-relevant $(relevant) ] ;
133
134    if python in $(relevant)
135    {
136        python = [ $(ps).get <python> ] ;
137    }
138
139    if $(python)
140    {
141        .info "  python=" $(python) ;
142
143        print.text "# python=$(python)" "" : true ;
144
145        print.text
146
147            "if(Boost_PYTHON_VERSION)"
148            "  string(REGEX REPLACE \"([0-9]+[.][0-9]+)([.].*)?\" \"\\\\1\" __boost_pyver ${Boost_PYTHON_VERSION})"
149            "  if(NOT __boost_pyver VERSION_EQUAL \"$(python)\")"
150            "    _BOOST_SKIPPED(\"$(fname)\" \"$(python), Boost_PYTHON_VERSION=${Boost_PYTHON_VERSION}\")"
151            "    return()"
152            "  endif()"
153            "endif()"
154            ""
155            "if(Boost_PYTHON_VERSION_MAJOR)"
156            "  if(NOT \"$(python)\" MATCHES \"^${Boost_PYTHON_VERSION_MAJOR}[.]\")"
157            "    _BOOST_SKIPPED(\"$(fname)\" \"$(python), Boost_PYTHON_VERSION_MAJOR=${Boost_PYTHON_VERSION_MAJOR}\")"
158            "    return()"
159            "  endif()"
160            "endif()"
161            ""
162            : true ;
163    }
164
165    print.text "# layout=$(layout)" "" : true ;
166
167    print.text "# toolset=$(toolset)" "" : true ;
168
169    if $(layout) = versioned
170    {
171        print.text
172
173            "if(Boost_COMPILER)"
174            "  if(NOT Boost_COMPILER STREQUAL \"$(toolset)\" AND NOT Boost_COMPILER STREQUAL \"-$(toolset)\")"
175            "    _BOOST_SKIPPED(\"$(fname)\" \"$(toolset), Boost_COMPILER=${Boost_COMPILER}\")"
176            "    return()"
177            "  endif()"
178            "else()"
179            "  if(BOOST_DETECTED_TOOLSET AND NOT BOOST_DETECTED_TOOLSET STREQUAL \"$(toolset)\")"
180            "    _BOOST_SKIPPED(\"$(fname)\" \"$(toolset), detected ${BOOST_DETECTED_TOOLSET}, set Boost_COMPILER to override\")"
181            "    return()"
182            "  endif()"
183            "endif()"
184            ""
185            : true ;
186    }
187
188    print.text "# link=$(link)" "" : true ;
189
190    if $(link) = static
191    {
192        print.text
193
194            "if(DEFINED Boost_USE_STATIC_LIBS)"
195            "  if(NOT Boost_USE_STATIC_LIBS)"
196            "    _BOOST_SKIPPED(\"$(fname)\" \"static, Boost_USE_STATIC_LIBS=${Boost_USE_STATIC_LIBS}\")"
197            "    return()"
198            "  endif()"
199            "else()"
200            "  if(NOT WIN32 AND NOT _BOOST_SINGLE_VARIANT)"
201            "    _BOOST_SKIPPED(\"$(fname)\" \"static, default is shared, set Boost_USE_STATIC_LIBS=ON to override\")"
202            "    return()"
203            "  endif()"
204            "endif()"
205            ""
206            : true ;
207    }
208    else
209    {
210        print.text
211
212            "if(DEFINED Boost_USE_STATIC_LIBS)"
213            "  if(Boost_USE_STATIC_LIBS)"
214            "    _BOOST_SKIPPED(\"$(fname)\" \"shared, Boost_USE_STATIC_LIBS=${Boost_USE_STATIC_LIBS}\")"
215            "    return()"
216            "  endif()"
217            "else()"
218            "  if(WIN32 AND NOT _BOOST_SINGLE_VARIANT)"
219            "    _BOOST_SKIPPED(\"$(fname)\" \"shared, default on Windows is static, set Boost_USE_STATIC_LIBS=OFF to override\")"
220            "    return()"
221            "  endif()"
222            "endif()"
223            ""
224            : true ;
225    }
226
227    print.text "# runtime-link=$(runtime-link)" "" : true ;
228
229    if $(runtime-link) = static
230    {
231        print.text
232
233            "if(NOT Boost_USE_STATIC_RUNTIME)"
234            "  _BOOST_SKIPPED(\"$(fname)\" \"static runtime, Boost_USE_STATIC_RUNTIME not ON\")"
235            "  return()"
236            "endif()"
237            ""
238            : true ;
239    }
240    else
241    {
242        print.text
243
244            "if(Boost_USE_STATIC_RUNTIME)"
245            "  _BOOST_SKIPPED(\"$(fname)\" \"shared runtime, Boost_USE_STATIC_RUNTIME=${Boost_USE_STATIC_RUNTIME}\")"
246            "  return()"
247            "endif()"
248            ""
249            : true ;
250    }
251
252    print.text "# runtime-debugging=$(runtime-debugging)" "" : true ;
253
254    if $(runtime-debugging) = "on"
255    {
256        print.text
257
258            "if(NOT \"${Boost_USE_DEBUG_RUNTIME}\" STREQUAL \"\" AND NOT Boost_USE_DEBUG_RUNTIME)"
259            "  _BOOST_SKIPPED(\"$(fname)\" \"debug runtime, Boost_USE_DEBUG_RUNTIME=${Boost_USE_DEBUG_RUNTIME}\")"
260            "  return()"
261            "endif()"
262            ""
263            : true ;
264    }
265    else
266    {
267        print.text
268
269            "if(Boost_USE_DEBUG_RUNTIME)"
270            "  _BOOST_SKIPPED(\"$(fname)\" \"release runtime, Boost_USE_DEBUG_RUNTIME=${Boost_USE_DEBUG_RUNTIME}\")"
271            "  return()"
272            "endif()"
273            ""
274            : true ;
275    }
276
277    print.text "# threading=$(threading)" "" : true ;
278
279    if $(layout) != system
280    {
281        if $(threading) = "multi"
282        {
283            print.text
284
285                "if(DEFINED Boost_USE_MULTITHREADED AND NOT Boost_USE_MULTITHREADED)"
286                "  _BOOST_SKIPPED(\"$(fname)\" \"multithreaded, Boost_USE_MULTITHREADED=${Boost_USE_MULTITHREADED}\")"
287                "  return()"
288                "endif()"
289                ""
290                : true ;
291        }
292        else
293        {
294            print.text
295
296                "if(NOT DEFINED Boost_USE_MULTITHREADED)"
297                "  _BOOST_SKIPPED(\"$(fname)\" \"single-threaded, Boost_USE_MULTITHREADED is not set and defaults to ON, set to OFF to override\")"
298                "  return()"
299                "endif()"
300                ""
301                "if(Boost_USE_MULTITHREADED)"
302                "  _BOOST_SKIPPED(\"$(fname)\" \"single-threaded, Boost_USE_MULTITHREADED=${Boost_USE_MULTITHREADED}\")"
303                "  return()"
304                "endif()"
305                ""
306                : true ;
307        }
308    }
309
310    print.text "# variant=$(variant)" "" : true ;
311
312    if $(variant) = debug
313    {
314        print.text
315
316            "if(NOT \"${Boost_USE_DEBUG_LIBS}\" STREQUAL \"\" AND NOT Boost_USE_DEBUG_LIBS)"
317            "  _BOOST_SKIPPED(\"$(fname)\" \"debug, Boost_USE_DEBUG_LIBS=${Boost_USE_DEBUG_LIBS}\")"
318            "  return()"
319            "endif()"
320            ""
321            : true ;
322    }
323    else
324    {
325        print.text
326
327            "if(NOT \"${Boost_USE_RELEASE_LIBS}\" STREQUAL \"\" AND NOT Boost_USE_RELEASE_LIBS)"
328            "  _BOOST_SKIPPED(\"$(fname)\" \"release, Boost_USE_RELEASE_LIBS=${Boost_USE_RELEASE_LIBS}\")"
329            "  return()"
330            "endif()"
331            ""
332            : true ;
333    }
334
335    print.text
336
337        "if(Boost_VERBOSE OR Boost_DEBUG)"
338        "  message(STATUS \"  [x] $(fname)\")"
339        "endif()"
340        ""
341        : true ;
342
343    if $(python)
344    {
345        print.text
346
347            "if(NOT Boost_PYTHON_VERSION)"
348            "  if(Boost_DEBUG)"
349            "    message(STATUS \"  Setting Boost_PYTHON_VERSION to $(python)\")"
350            "  endif()"
351            "  set(Boost_PYTHON_VERSION \"$(python)\")"
352            "endif()"
353            ""
354            : true ;
355    }
356
357    local lname = [ MATCH boost_(.*) : $(name) ] ;
358    .info "  lname=" $(lname) ;
359
360    local target = "Boost::$(lname)" ;
361    .info "  target=" $(target) ;
362
363    print.text
364
365        "# Create imported target $(target)"
366        ""
367        "if(NOT TARGET $(target))"
368        "  add_library($(target) $(link:U) IMPORTED)"
369        ""
370        "  set_target_properties($(target) PROPERTIES"
371        "    INTERFACE_INCLUDE_DIRECTORIES \"\${_BOOST_INCLUDEDIR}\""
372        "    INTERFACE_COMPILE_DEFINITIONS \"BOOST_ALL_NO_LIB\""
373        "  )"
374        "endif()"
375        ""
376        : true ;
377
378    print.text "# Target file name: $(fname)" "" : true ;
379
380    local lib-target-type = [ $(ps).get <boost-install.lib-target-type> ] ;
381    .info "  lib-target-type=" $(lib-target-type) ;
382
383    local loc-prop = LOCATION ;
384
385    if $(lib-target-type) = IMPORT_LIB
386    {
387        loc-prop = IMPLIB ;
388    }
389
390    .info "  loc-prop=" $(loc-prop) ;
391
392    print.text
393
394        "get_target_property(__boost_imploc $(target) IMPORTED_$(loc-prop)_$(variant:U))"
395        "if(__boost_imploc)"
396        "  message(SEND_ERROR \"Target $(target) already has an imported location '${__boost_imploc}', which is being overwritten with '${_BOOST_LIBDIR}/$(fname)'\")"
397        "endif()"
398        "unset(__boost_imploc)"
399        ""
400        "set_property(TARGET $(target) APPEND PROPERTY IMPORTED_CONFIGURATIONS $(variant:U))"
401        ""
402        "set_target_properties($(target) PROPERTIES"
403        "  IMPORTED_LINK_INTERFACE_LANGUAGES_$(variant:U) CXX"
404        "  IMPORTED_$(loc-prop)_$(variant:U) \"${_BOOST_LIBDIR}/$(fname)\""
405        "  )"
406        ""
407        : true ;
408
409    if $(variant) = release
410    {
411        print.text
412
413        "set_target_properties($(target) PROPERTIES"
414        "  MAP_IMPORTED_CONFIG_MINSIZEREL Release"
415        "  MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release"
416        "  )"
417        ""
418        : true ;
419    }
420
421    if $(link) = shared
422    {
423        print.text
424
425        "set_property(TARGET $(target) APPEND"
426        "  PROPERTY INTERFACE_COMPILE_DEFINITIONS \"BOOST_$(lname:U)_DYN_LINK\""
427        "  )"
428        ""
429        : true ;
430    }
431
432    local deps = [ MATCH "boost_(.*)" : [ $(ps).get <boost-install.dependency> ] ] headers ;
433    .info "  deps=" $(deps) ;
434
435    if $(deps)
436    {
437        print.text
438
439            "list(APPEND _BOOST_$(lname:U)_DEPS $(deps:S=:J= ))"
440            ""
441            : true ;
442    }
443}
444
445actions generate-cmake-variant-
446{
447}
448
449# tag
450
451local rule tag ( name : type ? : property-set )
452{
453    .debug tag $(name) ;
454
455    local link = [ $(property-set).get <link> ] ;
456    .debug "  link=" $(link) ;
457
458    local python = ;
459
460    local relevant = [ $(property-set).get <relevant> ] ;
461    relevant = [ feature.expand-relevant $(relevant) ] ;
462
463    if python in $(relevant)
464    {
465        python = [ $(property-set).get <python> ] ;
466        .debug "  python=" $(python) ;
467    }
468
469    local r = [ boostcpp.tag $(name) : STATIC_LIB : $(property-set) ] ;
470
471    r = $(r:S=$(name:S)) ;
472    r = $(r:B=$(r:B)-$(link)) ;
473
474    if $(python)
475    {
476        r = $(r:B=$(r:B)-py$(python)) ;
477    }
478
479    .debug "  result=" $(r) ;
480
481    return $(r) ;
482}
483
484# choose-lib-target: get the import library, if present, the
485#   shared/static library otherwise, ignore .pdb et al
486
487local rule choose-lib-target ( sources * )
488{
489    local result ;
490
491    for local t in $(sources)
492    {
493        if [ type.is-derived [ $(t).type ] IMPORT_LIB ]
494        {
495            return $(t) ;
496        }
497        else if [ type.is-derived [ $(t).type ] LIB ]
498        {
499            result = $(t) ;
500        }
501    }
502
503    return $(result) ;
504}
505
506# get-dependency-names: Returns the base names of all
507# dependency libraries.
508#
509local rule get-dependency-names ( sources * )
510{
511    local all-targets = [ collect-targets $(sources) ] ;
512    local lib-names ;
513    for local t in [ set.difference $(all-targets) : $(sources) ]
514    {
515        if [ $(t).type ] && [ type.is-derived [ $(t).type ] LIB ]
516        {
517            # Get back the original unmangled name of the library
518            local subvariant = [ $(t).creating-subvariant ] ;
519            local main-target = [ $(subvariant).main-target ] ;
520            lib-names += [ $(main-target).name ] ;
521        }
522    }
523    return [ sequence.unique $(lib-names) ] ;
524}
525
526# generate-cmake-variant
527
528rule generate-cmake-variant ( project name : property-set : sources * )
529{
530    .debug generate-cmake-variant $(name) ;
531
532    for local s in $(sources)
533    {
534        .debug "  name=" [ $(s).name ] ;
535    }
536
537    local lib-target = [ choose-lib-target $(sources) ] ;
538
539    local other-names = [ get-dependency-names $(sources) ] ;
540    property-set = [ $(property-set).add-raw <boost-install.dependency>$(other-names) ] ;
541
542    local result ;
543
544    if $(lib-target)
545    {
546        .debug "  lib-target=" [ $(lib-target).name ] ;
547
548        local lib-target-type = [ $(lib-target).type ] ;
549
550        .debug "  lib-target-type=" $(lib-target-type) ;
551
552        local tag = [ tag $(name) : : $(property-set) ] ;
553
554        property-set = [ $(property-set).add-raw <boost-install.lib-target-type>$(lib-target-type) ] ;
555
556        local a = [ new non-scanning-action $(lib-target) : boost-install.generate-cmake-variant- : $(property-set) ] ;
557
558        result += [ new file-target $(tag) : : $(project) : $(a) ] ;
559    }
560
561    # The result is an optional property set, the usage requirements,
562    # followed by a list of targets. When the list is empty, we need
563    # to include the property set, to avoid a warning.
564
565    return [ property-set.empty ] $(result) ;
566}
567
568# generate-cmake-config-
569
570local rule path-native-fwd ( path )
571{
572    path = [ path.native $(path) ] ;
573
574    if [ os.name ] = NT
575    {
576        path = $(path:T) ;
577    }
578
579    return $(path) ;
580}
581
582local rule get-dir ( name : dir )
583{
584    if [ path.is-rooted $(dir) ]
585    {
586        dir = [ path-native-fwd $(dir) ] ;
587
588        print.text
589
590            "set($(name) \"$(dir)\")"
591
592        : true ;
593    }
594    else
595    {
596        print.text
597
598            "get_filename_component($(name) \"${_BOOST_CMAKEDIR}/$(dir)/\" ABSOLUTE)"
599
600        : true ;
601    }
602}
603
604rule generate-cmake-config- ( target : sources * : properties * )
605{
606    .info generate-cmake-config- $(target) ":" $(sources) ;
607
608    local ps = [ property-set.create $(properties) ] ;
609
610    print.output $(target) ;
611
612    local version = [ $(ps).get <version> ] ;
613    .info "  version=" $(version) ;
614
615    local name = [ $(ps).get <name> ] ;
616    .info "  name=" $(name) ;
617
618    local library-type = [ $(ps).get <library-type> ] ;
619    .info "  library-type=" $(library-type) ;
620
621    local cmakedir = [ $(ps).get <boost-install.cmakedir> ] ;
622    .info "  cmakedir=" $(cmakedir) ;
623
624    local includedir = [ $(ps).get <boost-install.includedir> ] ;
625    .info "  includedir=" $(includedir) ;
626
627    local libdir = [ $(ps).get <boost-install.libdir> ] ;
628    .info "  libdir=" $(libdir) ;
629
630    local lname = [ MATCH boost_(.*) : $(name) ] ;
631    .info "  lname=" $(lname) ;
632
633    local ltarget = "Boost::$(lname)" ;
634    .info "  ltarget=" $(ltarget) ;
635
636    print.output $(target) ;
637
638    print.text
639
640        "# Generated by Boost $(version)"
641        ""
642        "if(TARGET $(ltarget))"
643        "  return()"
644        "endif()"
645        ""
646        "if(Boost_VERBOSE OR Boost_DEBUG)"
647        "  message(STATUS \"Found $(name) ${$(name)_VERSION} at ${$(name)_DIR}\")"
648        "endif()"
649        ""
650        "# Compute the include and library directories relative to this file."
651        ""
652        "get_filename_component(_BOOST_CMAKEDIR \"${CMAKE_CURRENT_LIST_DIR}/../\" REALPATH)"
653        : true ;
654
655    if [ path.is-rooted $(cmakedir) ]
656    {
657        local cmakedir-native = [ path-native-fwd $(cmakedir) ] ;
658
659        print.text
660
661            ""
662            "# If the computed and the original directories are symlink-equivalent, use original"
663            "if(EXISTS \"$(cmakedir-native)\")"
664            "  get_filename_component(_BOOST_CMAKEDIR_ORIGINAL \"$(cmakedir-native)\" REALPATH)"
665            "  if(_BOOST_CMAKEDIR STREQUAL _BOOST_CMAKEDIR_ORIGINAL)"
666            "    set(_BOOST_CMAKEDIR \"$(cmakedir-native)\")"
667            "  endif()"
668            "  unset(_BOOST_CMAKEDIR_ORIGINAL)"
669            "endif()"
670            ""
671            : true ;
672    }
673
674    get-dir "_BOOST_INCLUDEDIR" : $(includedir) ;
675
676    if $(library-type) = INTERFACE
677    {
678        print.text
679
680            ""
681            "add_library($(ltarget) INTERFACE IMPORTED)"
682            ""
683            "set_target_properties($(ltarget) PROPERTIES"
684            "  INTERFACE_INCLUDE_DIRECTORIES \"\${_BOOST_INCLUDEDIR}\""
685            "  INTERFACE_COMPILE_DEFINITIONS \"BOOST_ALL_NO_LIB\""
686            ")"
687            ""
688            "unset(_BOOST_INCLUDEDIR)"
689            "unset(_BOOST_CMAKEDIR)"
690            ""
691            : true ;
692    }
693    else
694    {
695        get-dir "_BOOST_LIBDIR" : $(libdir) ;
696
697        print.text
698
699            ""
700            "include(${CMAKE_CURRENT_LIST_DIR}/../BoostDetectToolset-$(version).cmake)"
701            ""
702            "if(Boost_DEBUG)"
703            "  message(STATUS \"Scanning ${CMAKE_CURRENT_LIST_DIR}/lib$(name)-variant*.cmake\")"
704            "endif()"
705            ""
706            "file(GLOB __boost_variants \"${CMAKE_CURRENT_LIST_DIR}/lib$(name)-variant*.cmake\")"
707            ""
708            "macro(_BOOST_SKIPPED fname reason)"
709            "  if(Boost_VERBOSE OR Boost_DEBUG)"
710            "    message(STATUS \"  [ ] ${fname}\")"
711            "  endif()"
712            "  list(APPEND __boost_skipped \"${fname} (${reason})\")"
713            "endmacro()"
714            ""
715            "list(LENGTH __boost_variants _BOOST_SINGLE_VARIANT)"
716            "if(NOT _BOOST_SINGLE_VARIANT EQUAL 1)"
717            "  set(_BOOST_SINGLE_VARIANT 0)"
718            "endif()"
719            ""
720            "foreach(f IN LISTS __boost_variants)"
721            "  if(Boost_DEBUG)"
722            "    message(STATUS \"  Including ${f}\")"
723            "  endif()"
724            "  include(${f})"
725            "endforeach()"
726            ""
727            "unset(_BOOST_SINGLE_VARIANT)"
728            "unset(_BOOST_LIBDIR)"
729            "unset(_BOOST_INCLUDEDIR)"
730            "unset(_BOOST_CMAKEDIR)"
731            ""
732            "if(NOT __boost_variants AND (Boost_VERBOSE OR Boost_DEBUG))"
733            "  message(STATUS \"  Library has no variants and is considered not found\")"
734            "endif()"
735            ""
736            "if(NOT TARGET $(ltarget))"
737            "  set(__boost_message \"No suitable build variant has been found.\")"
738            "  if(__boost_skipped)"
739            "    set(__boost_message \"${__boost_message}\\nThe following variants have been tried and rejected:\")"
740            "    foreach(s IN LISTS __boost_skipped)"
741            "      set(__boost_message \"${__boost_message}\\n* ${s}\")"
742            "    endforeach()"
743            "  endif()"
744            "  set($(name)_FOUND 0)"
745            "  set($(name)_NOT_FOUND_MESSAGE ${__boost_message})"
746            "  unset(__boost_message)"
747            "  unset(__boost_skipped)"
748            "  unset(__boost_variants)"
749            "  unset(_BOOST_$(lname:U)_DEPS)"
750            "  return()"
751            "endif()"
752            ""
753            "unset(__boost_skipped)"
754            "unset(__boost_variants)"
755            ""
756            "if(_BOOST_$(lname:U)_DEPS)"
757            "  list(REMOVE_DUPLICATES _BOOST_$(lname:U)_DEPS)"
758            "  if(Boost_VERBOSE OR Boost_DEBUG)"
759            "    message(STATUS \"Adding $(name) dependencies: ${_BOOST_$(lname:U)_DEPS}\")"
760            "  endif()"
761            "endif()"
762            ""
763            "foreach(dep_$(name) IN LISTS _BOOST_$(lname:U)_DEPS")
764            "  set(_BOOST_QUIET)"
765            "  if($(name)_FIND_QUIETLY)"
766            "    set(_BOOST_QUIET QUIET)"
767            "  endif()"
768            "  set(_BOOST_REQUIRED)"
769            "  if($(name)_FIND_REQUIRED)"
770            "    set(_BOOST_REQUIRED REQUIRED)"
771            "  endif()"
772            "  get_filename_component(_BOOST_CMAKEDIR \"${CMAKE_CURRENT_LIST_DIR}/../\" ABSOLUTE)"
773            "  find_package(boost_${dep_$(name)} $(version) EXACT CONFIG ${_BOOST_REQUIRED} ${_BOOST_QUIET} HINTS ${_BOOST_CMAKEDIR})"
774            "  set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES Boost::${dep_$(name)})"
775            "  unset(_BOOST_QUIET)"
776            "  unset(_BOOST_REQUIRED)"
777            "  unset(_BOOST_CMAKEDIR)"
778            "  if(NOT boost_${dep_$(name)}_FOUND)"
779            "    set($(name)_FOUND 0)"
780            "    set($(name)_NOT_FOUND_MESSAGE \"A required dependency, boost_${dep_$(name)}, has not been found.\")"
781            "    unset(_BOOST_$(lname:U)_DEPS)"
782            "    return()"
783            "  endif()"
784            "endforeach()"
785            ""
786            "unset(_BOOST_$(lname:U)_DEPS)"
787            ""
788            : true ;
789
790        if $(name) = boost_thread
791        {
792            print.text
793
794            "include(CMakeFindDependencyMacro)"
795            "find_dependency(Threads)"
796            "set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads)"
797            ""
798            : true ;
799        }
800
801        if $(name) = boost_mpi
802        {
803            print.text
804
805            "include(CMakeFindDependencyMacro)"
806            "find_dependency(MPI)"
807            ""
808            "if(MPI_CXX_FOUND AND NOT TARGET MPI::MPI_CXX)"
809            "  if(MPI_CXX_COMPILE_FLAGS)"
810            "    set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_COMPILE_OPTIONS \"${MPI_CXX_COMPILE_FLAGS}\")"
811            "  endif()"
812            "  if(MPI_CXX_INCLUDE_PATH)"
813            "    set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES \"${MPI_CXX_INCLUDE_PATH}\")"
814            "  endif()"
815            "  if(MPI_CXX_LINK_FLAGS)"
816            "    set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_OPTIONS \"SHELL:${MPI_CXX_LINK_FLAGS}\")"
817            "  endif()"
818            "  if(MPI_CXX_LIBRARIES)"
819            "    set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES \"${MPI_CXX_LIBRARIES}\")"
820            "  endif()"
821            "else()"
822            "  set_property(TARGET $(ltarget) APPEND PROPERTY INTERFACE_LINK_LIBRARIES MPI::MPI_CXX)"
823            "endif()"
824            ""
825            : true ;
826        }
827    }
828
829    print.text
830
831        "mark_as_advanced($(name)_DIR)"
832        ""
833        : true ;
834}
835
836actions generate-cmake-config-
837{
838}
839
840# generate-cmake-config
841
842rule generate-cmake-config ( project name : property-set : sources * )
843{
844    .debug generate-cmake-config $(name) ;
845
846    local pname = [ $(property-set).get <name> ] ;
847    local version = [ $(property-set).get <version> ] ;
848    local location = [ $(property-set).get <location> ] ;
849    local library-type = [ $(property-set).get <library-type> ] ;
850    local cmakedir = [ $(property-set).get <boost-install.cmakedir> ] ;
851    local includedir = [ $(property-set).get <boost-install.includedir> ] ;
852    local libdir = [ $(property-set).get <boost-install.libdir> ] ;
853
854    local ps = [ property-set.create
855        <name>$(pname) <version>$(version) <location>$(location)
856        <library-type>$(library-type)
857        <boost-install.cmakedir>$(cmakedir)
858        <boost-install.includedir>$(includedir)
859        <boost-install.libdir>$(libdir) ] ;
860
861    local result ;
862
863    local a = [ new non-scanning-action : boost-install.generate-cmake-config- : $(ps) ] ;
864
865    result += [ new file-target $(name) : : $(project) : $(a) ] ;
866
867    return $(result) ;
868}
869
870# generate-cmake-config-version-
871
872rule generate-cmake-config-version- ( target : sources * : properties * )
873{
874    .info generate-cmake-config-version- $(target) ":" $(sources) ;
875
876    local ps = [ property-set.create $(properties) ] ;
877
878    print.output $(target) ;
879
880    local version = [ $(ps).get <version> ] ;
881    .info "  version=" $(version) ;
882
883    print.output $(target) ;
884
885    print.text
886
887        "# Generated by Boost $(version)"
888        ""
889        "set(PACKAGE_VERSION $(version))"
890        ""
891        "if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)"
892        "  set(PACKAGE_VERSION_COMPATIBLE FALSE)"
893        "else()"
894        "  set(PACKAGE_VERSION_COMPATIBLE TRUE)"
895        "  if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)"
896        "    set(PACKAGE_VERSION_EXACT TRUE)"
897        "  endif()"
898        "endif()"
899        ""
900        : true ;
901}
902
903actions generate-cmake-config-version-
904{
905}
906
907# generate-cmake-config-version
908
909rule generate-cmake-config-version ( project name : property-set : sources * )
910{
911    .debug generate-cmake-config-version $(name) ;
912
913    local pname = [ $(property-set).get <name> ] ;
914    local version = [ $(property-set).get <version> ] ;
915    local location = [ $(property-set).get <location> ] ;
916
917    local ps = [ property-set.create <name>$(pname) <version>$(version) <location>$(location) ] ;
918
919    local result ;
920
921    local a = [ new non-scanning-action : boost-install.generate-cmake-config-version- : $(ps) ] ;
922
923    result += [ new file-target $(name) : : $(project) : $(a) ] ;
924
925    return $(result) ;
926}
927
928# install-cmake-config-
929
930local rule install-cmake-config- ( install-or-stage : location : includedir : libdir : version : name )
931{
932    #.debug install-cmake-config- $(name) ;
933
934    local r ;
935
936    if [ MATCH boost_(.*) : $(name) ]
937    {
938        local loc = $(location)/$(name)-$(version) ;
939
940        local library-type = UNKNOWN ;
941
942        if $(name) = boost_headers || $(name) = boost_math || $(name) = boost_exception
943        {
944            library-type = INTERFACE ;
945        }
946
947        local reqs = <name>$(name) <version>$(version) <library-type>$(library-type) <boost-install.cmakedir>$(location) <boost-install.includedir>$(includedir) <boost-install.libdir>$(libdir) ;
948
949        r += [ generate $(install-or-stage)/$(name)-config.cmake : $(name) : <generating-rule>@boost-install%generate-cmake-config $(reqs) ] ;
950        r += [ install $(install-or-stage)-$(name)-config.cmake : $(install-or-stage)/$(name)-config.cmake : <location>$(loc) ] ;
951
952        r += [ generate $(install-or-stage)/$(name)-config-version.cmake : $(name) : <generating-rule>@boost-install%generate-cmake-config-version $(reqs) ] ;
953        r += [ install $(install-or-stage)-$(name)-config-version.cmake : $(install-or-stage)/$(name)-config-version.cmake : <location>$(loc) ] ;
954
955        if $(library-type) != INTERFACE
956        {
957            local v = [ generate $(install-or-stage)/$(name)-variant.cmake : $(name) : <generating-rule>@boost-install%generate-cmake-variant $(reqs) ] ;
958            r += $(v) ;
959            r += [ install $(install-or-stage)-$(name)-config-variant.cmake : $(v) : <location>$(loc) ] ;
960        }
961    }
962    else
963    {
964        .info "target '$(name)' not prefixed by 'boost_', omitting CMake config" ;
965    }
966
967    return $(r) ;
968}
969
970# install-or-stage-cmake-config
971#
972# includedir, libdir, cmakedir should be in canonical path.make format
973
974rule install-or-stage-cmake-config ( name * : install-or-stage : includedir : libdir : cmakedir )
975{
976    local p = [ project.current ] ;
977
978    if "--no-cmake-config" in [ modules.peek : ARGV ]
979    {
980        alias $(install-or-stage)-cmake-config ;
981        $(p).mark-target-as-explicit $(install-or-stage)-cmake-config ;
982    }
983    else
984    {
985        includedir = [ path.relative-to $(cmakedir) $(includedir) ] ;
986        libdir = [ path.relative-to $(cmakedir) $(libdir) ] ;
987
988        local BOOST_VERSION = [ modules.peek boostcpp : BOOST_VERSION ] ;
989
990        local configs ;
991
992        for local nm in $(name)
993        {
994            configs += [ install-cmake-config- $(install-or-stage) : $(cmakedir) : $(includedir) : $(libdir) : $(BOOST_VERSION) : $(nm) ] ;
995        }
996
997        # Target install/stage-detect-toolset
998
999        local boost-install-dir = [ modules.binding $(__name__) ] ;
1000        boost-install-dir = $(boost-install-dir:D) ;
1001
1002        install $(install-or-stage)-detect-toolset : $(boost-install-dir)/BoostDetectToolset.cmake : <location>$(cmakedir) <name>BoostDetectToolset-$(BOOST_VERSION).cmake ;
1003        $(p).mark-target-as-explicit $(install-or-stage)-detect-toolset ;
1004
1005        # Target install/stage-boost-config
1006
1007        install $(install-or-stage)-boost-config : $(boost-install-dir)/BoostConfig.cmake : <location>$(cmakedir)/Boost-$(BOOST_VERSION) ;
1008        $(p).mark-target-as-explicit $(install-or-stage)-boost-config ;
1009
1010        # Target install/stage-boost-config-version
1011
1012        project.load [ path.make $(boost-install-dir) ] ;
1013
1014        install $(install-or-stage)-boost-config-version : /boost/tools/boost_install//BoostConfigVersion.cmake : <location>$(cmakedir)/Boost-$(BOOST_VERSION) ;
1015        $(p).mark-target-as-explicit $(install-or-stage)-boost-config-version ;
1016
1017        # Target install/stage-cmake-config
1018
1019        alias $(install-or-stage)-cmake-config : $(configs) $(install-or-stage)-detect-toolset $(install-or-stage)-boost-config $(install-or-stage)-boost-config-version ;
1020        $(p).mark-target-as-explicit $(install-or-stage)-cmake-config ;
1021    }
1022}
1023
1024# install-cmake-config
1025
1026rule install-cmake-config ( name * )
1027{
1028    #.debug install-cmake-config $(name) ;
1029
1030    local includedir = [ boost-install-dirs.includedir ] ;
1031    local libdir = [ boost-install-dirs.libdir ] ;
1032    local cmakedir = [ boost-install-dirs.cmakedir ] ;
1033    local header-subdir = [ boost-install-dirs.header-subdir ] ;
1034
1035    if $(header-subdir)
1036    {
1037        includedir = $(includedir)/$(header-subdir) ;
1038    }
1039
1040    install-or-stage-cmake-config $(name) : install : $(includedir) : $(libdir) : $(cmakedir) ;
1041}
1042
1043rule stage-cmake-config ( name * )
1044{
1045    local includedir = [ path.make [ modules.peek boostcpp : BOOST_ROOT ] ] ;
1046    local libdir = [ boost-install-dirs.stage-libdir ] ;
1047    local cmakedir = $(libdir)/cmake ;
1048
1049    install-or-stage-cmake-config $(name) : stage : $(includedir) : $(libdir) : $(cmakedir) ;
1050}
1051
1052# stage-cmake-config
1053
1054# collect-targets: Returns the targets and all their dependencies.
1055# Copied from stage.jam
1056# TODO: Factor this out as a utility in virtal-target.jam
1057
1058rule collect-targets ( targets * )
1059{
1060    # Find subvariants
1061    local s ;
1062    for local t in $(targets)
1063    {
1064        s += [ $(t).creating-subvariant ] ;
1065    }
1066    s = [ sequence.unique $(s) ] ;
1067
1068    local result = [ new set ] ;
1069    $(result).add $(targets) ;
1070
1071    for local i in $(s)
1072    {
1073        $(i).all-referenced-targets $(result) ;
1074    }
1075    local result2 ;
1076    for local r in [ $(result).list ]
1077    {
1078        if $(r:G) != <use>
1079        {
1080            result2 += $(r:G=) ;
1081        }
1082    }
1083    DELETE_MODULE $(result) ;
1084    return [ sequence.unique $(result2) ] ;
1085}
1086
1087# get-dependency-projects: Returns all the projects of any dependency of the sources.
1088
1089rule get-dependency-projects ( sources * )
1090{
1091    local result ;
1092    for local t in [ collect-targets $(sources) ]
1093    {
1094        result += [ $(t).project ] ;
1095    }
1096    return [ sequence.unique $(result) ] ;
1097}
1098
1099# generate-dependencies: find and generate the stage and install targets
1100# corresponding to the source libraries.
1101
1102rule generate-dependencies ( project name ? : property-set : sources * )
1103{
1104    local stage-targets ;
1105    local stage-or-install = [ $(property-set).get <name> ] ;
1106    local excluded-projects = $(project) [ $(project).find /boost ] ;
1107    for local p in [ get-dependency-projects $(sources) ] [ $(project).find /boost/headers ]
1108    {
1109        if ! ( $(p) in $(excluded-projects) )
1110        {
1111            stage-targets += [ $(p).find $(stage-or-install) : no-error ] ;
1112        }
1113    }
1114    local props = [ $(property-set).propagated ] ;
1115    local result ;
1116    local usage-requirements = [ property-set.empty ] ;
1117    for local t in $(stage-targets)
1118    {
1119        local g = [ $(t).generate $(props) ] ;
1120        usage-requirements = [ $(usage-requirements).add $(g[1]) ] ;
1121        result += $(g[2-]) ;
1122    }
1123    return $(usage-requirements) $(result) ;
1124}
1125
1126# boost-install
1127
1128local rule install-stage-subdir ( properties * )
1129{
1130    local ps = [ property-set.create $(properties) ] ;
1131
1132    local r = [ boostcpp.tag boost : STATIC_LIB : $(ps) ] ;
1133
1134    r = $(r:S=) ;
1135
1136    local r2 = [ MATCH "lib(.*)" : $(r) ] ;
1137    if $(r2) { r = $(r2) ; }
1138
1139    local python = [ $(ps).get <python> ] ;
1140
1141    if $(python)
1142    {
1143        r = $(r:B=$(r:B)-python$(python)) ;
1144    }
1145
1146    return $(r) ;
1147}
1148
1149rule stage-subdir ( properties * )
1150{
1151    local r = [ install-stage-subdir $(properties) ] ;
1152
1153    local libdir = [ boost-install-dirs.stage-libdir ] ;
1154
1155    return <location>$(libdir)/$(r) ;
1156}
1157
1158rule install-subdir ( properties * )
1159{
1160    local r = [ install-stage-subdir $(properties) ] ;
1161
1162    local libdir = [ boost-install-dirs.libdir ] ;
1163
1164    return <location>$(libdir)/$(r) ;
1165}
1166
1167rule boost-install ( libraries * )
1168{
1169    .debug boost-install $(libraries) ;
1170
1171    local l2 = ;
1172    local unprefixed = ;
1173
1174    for local lib in $(libraries)
1175    {
1176        if [ MATCH boost_(.*) : $(lib) ]
1177        {
1178            l2 += $(lib) ;
1179        }
1180        else
1181        {
1182            unprefixed += $(lib) ;
1183        }
1184    }
1185
1186    libraries = $(l2) ;
1187
1188    # Target install
1189
1190    local p = [ project.current ] ;
1191
1192    package.install install-libraries Boost
1193        : <install-no-version-symlinks>on
1194        : # No binaries
1195        : $(libraries)
1196        : # No headers
1197    ;
1198
1199    $(p).mark-target-as-explicit install-libraries ;
1200
1201    install install-unprefixed-static : $(unprefixed) : <install-type>STATIC_LIB <conditional>@boost-install%install-subdir ;
1202    $(p).mark-target-as-explicit install-unprefixed-static ;
1203
1204    install install-unprefixed-shared : $(unprefixed) : <install-type>SHARED_LIB <install-no-version-symlinks>on <conditional>@boost-install%install-subdir ;
1205    $(p).mark-target-as-explicit install-unprefixed-shared ;
1206
1207    install-cmake-config $(libraries) ;
1208
1209    generate install-dependencies : $(libraries) : <generating-rule>@boost-install%generate-dependencies <name>install ;
1210    $(p).mark-target-as-explicit install-dependencies ;
1211
1212    alias install : install-libraries install-unprefixed-static install-unprefixed-shared install-cmake-config install-dependencies ;
1213    $(p).mark-target-as-explicit install ;
1214
1215    # Target stage
1216
1217    local stage-libdir = [ boost-install-dirs.stage-libdir ] ;
1218
1219    stage-cmake-config $(libraries) ;
1220
1221    install stage-libraries-static : $(libraries) : <location>$(stage-libdir) <install-dependencies>on <install-type>STATIC_LIB ;
1222    $(p).mark-target-as-explicit stage-libraries-static ;
1223
1224    install stage-libraries-shared : $(libraries) : <location>$(stage-libdir) <install-dependencies>on <install-type>SHARED_LIB <install-no-version-symlinks>on ;
1225    $(p).mark-target-as-explicit stage-libraries-shared ;
1226
1227    install stage-unprefixed-static : $(unprefixed) : <install-type>STATIC_LIB <conditional>@boost-install%stage-subdir ;
1228    $(p).mark-target-as-explicit stage-unprefixed-static ;
1229
1230    install stage-unprefixed-shared : $(unprefixed) : <install-type>SHARED_LIB <install-no-version-symlinks>on <conditional>@boost-install%stage-subdir ;
1231    $(p).mark-target-as-explicit stage-unprefixed-shared ;
1232
1233    generate stage-dependencies : $(libraries) : <generating-rule>@boost-install%generate-dependencies <name>stage ;
1234    $(p).mark-target-as-explicit stage-dependencies ;
1235
1236    alias stage : stage-libraries-static stage-libraries-shared stage-unprefixed-static stage-unprefixed-shared stage-cmake-config stage-dependencies ;
1237    $(p).mark-target-as-explicit stage ;
1238}
1239