2022-04-29 12:03:08 +01:00
< div id = "flow-diagram" >
< div class = "diagram-grid" v-bind:style = "gridStyle" >
<!-- BEHIND THE GRID CONTENT -->
<!-- line for each platform -->
< div class = "grid-line" style = "grid-row-start: 3" ></ div >
< div class = "grid-line" style = "grid-row-start: 4" ></ div >
< div class = "grid-line" style = "grid-row-start: 5" ></ div >
2026-04-10 22:39:28 +05:30
< div class = "grid-line" style = "grid-row-start: 6" ></ div >
< div class = "grid-line" style = "grid-row-start: 7" ></ div >
< div class = "grid-line" style = "grid-row-start: 8" ></ div >
2022-04-29 12:03:08 +01:00
<!-- the docker container outline -->
< div class = "grid-outline docker" >
< div class = "outline" >
2022-06-27 18:30:49 +01:00
Manylinux container
2022-04-29 12:03:08 +01:00
</ div >
</ div >
<!-- the venv outlines -->
< div class = "grid-outline testVenv" style = "grid-row-start: 3" >
< div class = "outline" > Test virtualenv</ div >
</ div >
< div class = "grid-outline testVenv" style = "grid-row-start: 4" >< div class = "outline" ></ div ></ div >
< div class = "grid-outline testVenv" style = "grid-row-start: 5" >< div class = "outline" ></ div ></ div >
2026-04-10 22:39:28 +05:30
< div class = "grid-outline testVenv" style = "grid-row-start: 6" >< div class = "outline" ></ div ></ div >
< div class = "grid-outline testVenv" style = "grid-row-start: 7" >< div class = "outline" ></ div ></ div >
< div class = "grid-outline testVenv" style = "grid-row-start: 8" >< div class = "outline" ></ div ></ div >
2022-04-29 12:03:08 +01:00
<!-- THE GRID CONTENT -->
<!-- the row labels -->
< div class = "grid-row-label" style = "grid-row-start: 3" > Linux</ div >
< div class = "grid-row-label" style = "grid-row-start: 4" > macOS</ div >
< div class = "grid-row-label" style = "grid-row-start: 5" > Windows</ div >
2026-04-10 22:39:28 +05:30
< div class = "grid-row-label" style = "grid-row-start: 6" > Android</ div >
< div class = "grid-row-label" style = "grid-row-start: 7" > iOS</ div >
< div class = "grid-row-label" style = "grid-row-start: 8" > Pyodide</ div >
2022-04-29 12:03:08 +01:00
<!-- the column labels -->
< div class = "grid-column-label"
style = "grid-row: 1 / span 1; grid-column: 5 / -3" >
< div class = "label" > For each version of Python</ div >
</ div >
< div class = "grid-column-label"
style = "grid-row: 2 / span 1;
2026-05-14 15:41:14 +01:00
grid-column: 10 / -3;
2022-04-29 12:03:08 +01:00
margin-bottom: 0.5em;" >
< div class = "label" > If tests are configured</ div >
</ div >
<!-- the steps -->
< div class = "step" v-for = "(step, sIndex) in diagram.steps" >
< component v-for = "action in step"
class = "action"
v-bind:is = "action.href ? 'a' : 'div'"
v-bind:href = "action.href" >
< div class = "dots" v-if = "action.style == 'dot'" >
< div class = "dot"
v-info = "action"
v-for = "(platform, pIndex) in platforms"
v-if = "action.platforms.includes(platform)"
v-bind:style = "{gridRowStart: `${pIndex+3}`,
gridColumnStart: `${sIndex+2}`}" >
< div class = "dot-graphic" ></ div >
</ div >
</ div >
< div class = "block-container" v-if = "action.style == 'block'" >
< div class = "block"
v-info = "action"
v-bind:style = "{...blockStyle(action),
gridColumnStart: `${sIndex+2}`}" >
{{action.label}}
</ div >
</ div >
</ a >
</ div >
</ div >
</ div >
2022-05-09 14:24:03 +01:00
< noscript >
< img src = "data/how-it-works.png" alt = "Diagram showing the steps for each platform" >
< p >< strong > Enable JavaScript for an interactive version of this diagram.</ strong ></ p >
</ noscript >
2022-04-29 12:03:08 +01:00
< script type = "module" async >
import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js'
import 'https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js'
import 'https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.js'
const diagram = {
steps : [
[
{
2022-06-27 18:30:49 +01:00
label : 'copy project into container' ,
2022-04-29 12:03:08 +01:00
platforms : [ 'linux' ],
style : 'block' ,
width : 2 ,
},
],
[], // empty column so that the manylinux outline intersects the previous column in the middle.
[
{
href : 'options/#before-all' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'dot' ,
tooltip : {
title : 'CIBW_BEFORE_ALL' ,
tag : 'Optional step' ,
description : 'Execute a shell command on the build system before any wheels are built.'
},
},
],
[
{
label : 'Install Python' ,
platforms : [ 'macos' , 'windows' ],
style : 'block' ,
tooltip : {
description : 'Install the version of Python required to build this wheel.'
},
},
2026-04-10 22:39:28 +05:30
{
label : 'Install Python & set up cross-compilation' ,
platforms : [ 'android' , 'ios' ],
style : 'block' ,
tooltip : {
description : 'Install Python for the build and target platforms, and set up a cross-compilation environment.'
},
},
{
label : 'Set up Pyodide xbuildenv' ,
platforms : [ 'pyodide' ],
style : 'block' ,
tooltip : {
description : 'Install a base Python, set up a build virtualenv with pyodide-build, install the Pyodide cross-build environment and Emscripten toolchain.'
},
},
2022-04-29 12:03:08 +01:00
],
[
{
href : 'options/#before-build' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'dot' ,
tooltip : {
title : 'CIBW_BEFORE_BUILD' ,
tag : 'Optional step' ,
description : "Execute a shell command preparing each wheel's build." ,
},
},
],
[
{
label : 'Build wheel' ,
href : 'options/#build-frontend' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'block' ,
tooltip : {
title : 'CIBW_BUILD_FRONTEND' ,
tag : 'Customisable step' ,
2026-04-10 22:39:28 +05:30
description : 'Build the wheel according to your package configuration, using the frontend of your choice – pip, build, or uv.'
2022-04-29 12:03:08 +01:00
},
},
],
[
{
label : 'Repair using auditwheel' ,
href : 'options/#repair-wheel-command' ,
platforms : [ 'linux' ],
style : 'block' ,
tooltip : {
title : 'CIBW_REPAIR_WHEEL_COMMAND' ,
tag : 'Customisable step' ,
description : 'Bundle shared libraries and ensure manylinux compliance by running auditwheel on each built wheel.'
},
},
{
label : 'Repair using delocate' ,
href : 'options/#repair-wheel-command' ,
platforms : [ 'macos' ],
style : 'block' ,
tooltip : {
title : 'CIBW_REPAIR_WHEEL_COMMAND' ,
tag : 'Customisable step' ,
description : 'Bundle shared libraries by running delocate on each built wheel.'
},
},
{
2026-05-29 05:27:28 +01:00
label : 'Repair using auditwheel' ,
2022-04-29 12:03:08 +01:00
href : 'options/#repair-wheel-command' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'android' ],
style : 'block' ,
tooltip : {
title : 'CIBW_REPAIR_WHEEL_COMMAND' ,
tag : 'Customisable step' ,
2026-05-29 05:27:28 +01:00
description : 'Bundle shared libraries by running auditwheel on each built wheel.'
2026-04-10 22:39:28 +05:30
},
},
{
2026-05-29 13:51:09 -04:00
label : 'Repair using delvewheel' ,
2026-04-10 22:39:28 +05:30
href : 'options/#repair-wheel-command' ,
2026-05-29 13:51:09 -04:00
platforms : [ 'windows' ],
style : 'block' ,
tooltip : {
title : 'CIBW_REPAIR_WHEEL_COMMAND' ,
tag : 'Customisable step' ,
description : 'Bundle shared libraries by running delvewheel on each built wheel.'
},
},
{
href : 'options/#repair-wheel-command' ,
platforms : [ 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'dot' ,
tooltip : {
title : 'CIBW_REPAIR_WHEEL_COMMAND' ,
tag : 'Optional step' ,
2026-04-10 22:39:28 +05:30
description : 'Execute a shell command to repair each built wheel.'
2022-04-29 12:03:08 +01:00
},
},
],
2026-05-14 15:41:14 +01:00
[
{
env : "CIBW_AUDIT_COMMAND" ,
href : 'options/#audit-command' ,
label : 'audit wheel' ,
platforms : [ 'linux' , 'macos' , 'windows' ],
style : 'dot' ,
tooltip : {
title : 'CIBW_AUDIT_COMMAND' ,
tag : 'Optional step' ,
description : 'Runs a shell command to check each built wheel. By default this runs abi3audit if produced wheels are abi3.'
},
}
],
2022-04-29 12:03:08 +01:00
[
{
href : 'options/#before-test' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'dot' ,
tooltip : {
title : 'CIBW_BEFORE_TEST' ,
tag : 'Optional step' ,
description : 'Execute a shell command before testing each wheel'
},
},
],
[
{
label : 'Install wheel' ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
style : 'block' ,
tooltip : {
2026-04-10 22:39:28 +05:30
description : 'Install the wheel we just built into the test environment.'
2022-04-29 12:03:08 +01:00
},
},
],
[
{
label : 'Test wheel' ,
href : 'options/#test-command' ,
platforms : [ 'linux' , 'macos' , 'windows' ],
style : 'block' ,
tooltip : {
title : 'CIBW_TEST_COMMAND' ,
tag : 'Optional step' ,
2026-04-10 22:39:28 +05:30
description : 'Execute a shell command to test each built wheel.'
},
},
{
label : 'Test on emulator' ,
href : 'options/#test-command' ,
platforms : [ 'android' ],
style : 'block' ,
tooltip : {
title : 'CIBW_TEST_COMMAND' ,
tag : 'Optional step' ,
description : 'Run the test command on an Android emulator using the CPython testbed.'
},
},
{
label : 'Test on simulator' ,
href : 'options/#test-command' ,
platforms : [ 'ios' ],
style : 'block' ,
tooltip : {
title : 'CIBW_TEST_COMMAND' ,
tag : 'Optional step' ,
description : 'Run the test command on an iOS simulator using the testbed app.'
},
},
{
label : 'Test in Node.js' ,
href : 'options/#test-command' ,
platforms : [ 'pyodide' ],
style : 'block' ,
tooltip : {
title : 'CIBW_TEST_COMMAND' ,
tag : 'Optional step' ,
description : 'Run the test command in a Pyodide virtualenv powered by Node.js.'
2022-04-29 12:03:08 +01:00
},
},
],
[
{
2022-06-27 18:30:49 +01:00
label : 'Copy wheels out of container' ,
2022-04-29 12:03:08 +01:00
platforms : [ 'linux' ],
style : 'block' ,
width : 2 ,
},
],
[],
]
}
const diagramComponent = new Vue ({
el : '#flow-diagram' ,
data () {
return {
diagram ,
2026-04-10 22:39:28 +05:30
platforms : [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ],
2022-04-29 12:03:08 +01:00
}
},
methods : {
blockStyle ( action ) {
2026-04-10 22:39:28 +05:30
const platformOrder = [ 'linux' , 'macos' , 'windows' , 'android' , 'ios' , 'pyodide' ]
const rowOffset = 3 // first platform starts at grid row 3
2022-04-29 12:03:08 +01:00
2026-04-10 22:39:28 +05:30
let start = null
let end = null
for ( let i = 0 ; i < platformOrder . length ; i ++ ) {
if ( action . platforms . includes ( platformOrder [ i ])) {
if ( start === null ) start = rowOffset + i
end = rowOffset + i + 1
}
2022-04-29 12:03:08 +01:00
}
return {
gridRowStart : start . toString (),
gridRowEnd : end . toString (),
gridColumnEnd : `span ${ action . width || 1 } ` ,
}
}
},
computed : {
gridStyle () {
return {
gridTemplateRows : `auto auto repeat( ${ this . platforms . length } , 1fr)` ,
gridTemplateColumns : `repeat( ${ this . diagram . steps . length + 1 } , auto)` ,
}
},
},
directives : {
info : {
inserted ( el , binding ) {
const action = binding . value
2022-05-09 13:31:47 +01:00
const { env , label , optional = false , description = '' , href = '' } = action
2022-04-29 12:03:08 +01:00
const tooltip = action . tooltip
if ( tooltip ) {
2022-05-02 11:11:02 +01:00
const tippyInstance = tippy ( el , {
2022-04-29 12:03:08 +01:00
content : `
2022-05-09 13:31:47 +01:00
<a class="tooltip-contents" href=" ${ href || '' } ">
<div class="tooltip-title">
${ tooltip . title || '' }
</div>
<div class="tooltip-tag">
${ tooltip . tag || '' }
</div>
<div class="tooltip-description">
${ tooltip . description }
</div>
</a>
2022-04-29 12:03:08 +01:00
` ,
placement : 'right-start' ,
allowHTML : true ,
maxWidth : 'none' ,
appendTo : document . getElementById ( 'flow-diagram' ),
offset : [ 0 , 10 ],
2022-05-09 13:31:47 +01:00
onShow ( instance ) {
2022-05-02 11:11:02 +01:00
const stepEl = el . closest ( '.action' )
stepEl . classList . add ( 'tooltip-open' )
2022-05-09 13:31:47 +01:00
instance . setProps ({
interactive : tippy . currentInput . isTouch
})
2022-05-02 11:11:02 +01:00
},
onHide () {
const stepEl = el . closest ( '.action' )
stepEl . classList . remove ( 'tooltip-open' )
}
})
2022-05-09 13:31:47 +01:00
el . addEventListener ( 'click' , e => {
// click event should just open the tooltip on touch devices
if ( tippy . currentInput . isTouch ) {
e . preventDefault ()
}
2022-04-29 12:03:08 +01:00
})
}
}
}
}
})
</ script >
< style >
# flow-diagram {
background : #fcfcfc ;
/* font-family: Inter; */
/* font-size: 10px; */
font-size : 0.7 em ;
padding-bottom : 2 em ;
}
2022-05-09 14:24:03 +01:00
. no-js # flow-diagram {
display : none
}
2022-04-29 12:03:08 +01:00
. diagram-grid {
display : grid ;
overflow-x : auto ;
}
. platform , . step , . dots , . block-container , . action {
display : contents ;
}
. block , . dot {
position : relative ;
margin : 2 em 0.5 em ;
}
. block {
background-color : #eee ;
/* margin: 0.5em auto; */
padding : 0.5 em ;
max-width : 6 em ;
display : flex ;
align-items : center ;
justify-content : center ;
text-align : center ;
}
. dot {
/* margin: 0.5em; */
display : flex ;
align-items : center ;
justify-content : center ;
}
. dot-graphic {
width : 1.3 em ;
height : 1.3 em ;
border-radius : 50 % ;
background : #DADADA ;
}
a . action {
color : inherit ;
}
2022-05-02 11:11:02 +01:00
. action . tooltip-open . dot-graphic {
2022-04-29 12:03:08 +01:00
background-color : #416EDA ;
}
2022-05-02 11:11:02 +01:00
. action . tooltip-open . block {
2022-04-29 12:03:08 +01:00
background-color : #416EDA ;
color : white ;
}
. grid-column-label {
height : 2 em ;
position : relative ;
display : flex ;
align-items : center ;
justify-content : center ;
margin : 0 0.5 em ;
}
. grid-column-label :: before {
content : "" ;
height : 1 px ;
background-color : currentColor ;
position : absolute ;
top : calc ( 50 % - 0.5 px );
left : 0 ;
right : 0 ;
}
. grid-column-label . label {
background : #fcfcfc ;
2022-09-18 13:46:49 +01:00
padding : 0 1 em ;
2022-04-29 12:03:08 +01:00
position : relative ;
}
. grid-row-label {
grid-column : 1 / span 1 ;
display : flex ;
align-items : center ;
justify-content : flex-end ;
text-align : right ;
background : #fcfcfc ;
position : relative ;
padding-right : 1 em ;
font-size : 1.1 em ;
}
. grid-line {
grid-column : 1 / -1 ;
grid-row-end : span 1 ;
position : relative ;
}
. grid-line :: after {
content : "" ;
height : 1 px ;
background-color : #979797 ;
position : absolute ;
top : calc ( 50 % - 1 px );
left : 0 ;
right : 0 ;
}
. grid-outline {
grid-row-end : span 1 ;
position : relative ;
2026-04-10 22:39:28 +05:30
color : #666666 ;
2022-04-29 12:03:08 +01:00
}
. grid-outline . docker {
grid-row : 3 / span 1 ;
grid-column : 3 / -2 ;
}
. grid-outline . testVenv {
2026-05-14 15:41:14 +01:00
grid-column : 10 / span 3 ;
2022-04-29 12:03:08 +01:00
}
. grid-outline . outline {
position : absolute ;
border : 1 px solid #e5e5e5 ;
padding : 1 px 3 px ;
}
. grid-outline . docker . outline {
left : 0 ;
right : 0 ;
top : 0 ;
bottom : 0 ;
}
. grid-outline . testVenv . outline {
left : 0 ;
right : 0 ;
top : 0.5 em ;
bottom : 0.5 em ;
}
/* style the tooltip */
. tippy-box {
background : white ;
box-shadow : 0 2 px 6 px -1 px rgba ( 0 , 0 , 0 , 0.12 );
border-radius : 0 ;
text-align : left ;
font-size : 1 em ;
color : #1F1F1F ;
border : 1 px solid rgba ( 0 , 0 , 0 , 0.02 );
width : 14 em ;
min-width : min-content ;
}
. tippy-box [ data-placement ^= 'top' ] > . tippy-arrow :: before {
border-top-color : white ;
}
. tippy-box [ data-placement ^= 'bottom' ] > . tippy-arrow :: before {
border-bottom-color : white ;
}
. tippy-box [ data-placement ^= 'left' ] > . tippy-arrow :: before {
border-left-color : white ;
}
. tippy-box [ data-placement ^= 'right' ] > . tippy-arrow :: before {
border-right-color : white ;
}
2022-05-09 13:31:47 +01:00
a . tooltip-contents {
color : inherit ;
text-decoration : none ;
display : block ;
}
2022-04-29 12:03:08 +01:00
. tooltip-title {
font-weight : 600 ;
font-size : 1.1 em ;
color : #416EDA ;
}
. tooltip-tag {
font-weight : 500 ;
text-transform : uppercase ;
font-size : 0.9 em ;
2026-04-10 22:39:28 +05:30
color : #888888 ;
2022-04-29 12:03:08 +01:00
}
. tooltip-description {
margin-top : 1 px ;
margin-bottom : 2 px ;
}
</ style >