2023-11-01 06:11:15 +08:00
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
F i n d M P I
- - - - - - -
F i n d a M e s s a g e P a s s i n g Interface ( MPI ) i m p l e m e n t a t i o n .
T h e M e s s a g e P a s s i n g Interface ( MPI ) i s a l i b r a r y u s e d t o w r i t e
h i g h - p e r f o r m a n c e d i s t r i b u t e d - m e m o r y p a r a l l e l a p p l i c a t i o n s , a n d i s
t y p i c a l l y d e p l o y e d o n a c l u s t e r . M P I i s a s t a n d a r d interface ( defined
b y t h e M P I f o r u m ) f o r w h i c h m a n y i m p l e m e n t a t i o n s a r e a v a i l a b l e .
V a r i a b l e s f o r u s i n g M P I
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
T h e m o d u l e e x p o s e s t h e c o m p o n e n t s ` ` C ` ` , ` ` C X X ` ` , ` ` M P I C X X ` ` a n d ` ` F o r t r a n ` ` .
E a c h o f t h e s e c o n t r o l s t h e v a r i o u s M P I l a n g u a g e s t o s e a r c h f o r .
T h e d i f f e r e n c e b e t w e e n ` ` C X X ` ` a n d ` ` M P I C X X ` ` i s t h a t ` ` C X X ` ` r e f e r s t o t h e
M P I C A P I b e i n g u s a b l e f r o m C + + , w h e r e a s ` ` M P I C X X ` ` r e f e r s t o t h e M P I - 2 C + + A P I
t h a t w a s r e m o v e d a g a i n i n M P I - 3 .
D e p e n d i n g o n t h e e n a b l e d c o m p o n e n t s t h e f o l l o w i n g v a r i a b l e s w i l l b e s e t :
` ` M P I _ F O U N D ` `
V a r i a b l e i n d i c a t i n g t h a t M P I s e t t i n g s f o r a l l r e q u e s t e d l a n g u a g e s h a v e b e e n f o u n d .
I f n o c o m p o n e n t s a r e s p e c i f i e d , t h i s i s t r u e i f M P I s e t t i n g s f o r a l l e n a b l e d l a n g u a g e s
w e r e d e t e c t e d . N o t e t h a t t h e ` ` M P I C X X ` ` c o m p o n e n t d o e s n o t a f f e c t t h i s v a r i a b l e .
` ` M P I _ V E R S I O N ` `
M i n i m a l v e r s i o n o f M P I d e t e c t e d a m o n g t h e r e q u e s t e d l a n g u a g e s , o r a l l e n a b l e d l a n g u a g e s
i f n o c o m p o n e n t s w e r e s p e c i f i e d .
T h i s m o d u l e w i l l s e t t h e f o l l o w i n g v a r i a b l e s p e r l a n g u a g e i n y o u r
p r o j e c t , w h e r e ` ` < l a n g > ` ` i s o n e o f C , C X X , o r F o r t r a n :
` ` M P I _ < l a n g > _ F O U N D ` `
V a r i a b l e i n d i c a t i n g t h e M P I s e t t i n g s f o r ` ` < l a n g > ` ` w e r e f o u n d a n d t h a t
s i m p l e M P I t e s t p r o g r a m s c o m p i l e w i t h t h e p r o v i d e d s e t t i n g s .
` ` M P I _ < l a n g > _ C O M P I L E R ` `
M P I c o m p i l e r f o r ` ` < l a n g > ` ` i f s u c h a p r o g r a m e x i s t s .
` ` M P I _ < l a n g > _ C O M P I L E _ O P T I O N S ` `
C o m p i l a t i o n o p t i o n s f o r M P I p r o g r a m s i n ` ` < l a n g > ` ` , g i v e n a s a : r e f : ` ; - l i s t < C M a k e L a n g u a g e L i s t s > ` .
` ` M P I _ < l a n g > _ C O M P I L E _ D E F I N I T I O N S ` `
C o m p i l a t i o n d e f i n i t i o n s f o r M P I p r o g r a m s i n ` ` < l a n g > ` ` , g i v e n a s a : r e f : ` ; - l i s t < C M a k e L a n g u a g e L i s t s > ` .
` ` M P I _ < l a n g > _ I N C L U D E _ D I R S ` `
I n c l u d e path ( s ) f o r M P I h e a d e r .
` ` M P I _ < l a n g > _ L I N K _ F L A G S ` `
L i n k e r f l a g s f o r M P I p r o g r a m s .
` ` M P I _ < l a n g > _ L I B R A R I E S ` `
A l l l i b r a r i e s t o l i n k M P I p r o g r a m s a g a i n s t .
A d d i t i o n a l l y , t h e f o l l o w i n g : p r o p _ t g t : ` I M P O R T E D ` t a r g e t s a r e d e f i n e d :
` ` M P I : : M P I _ < l a n g > ` `
T a r g e t f o r u s i n g M P I f r o m ` ` < l a n g > ` ` .
T h e f o l l o w i n g v a r i a b l e s i n d i c a t i n g w h i c h b i n d i n g s a r e p r e s e n t w i l l b e d e f i n e d :
` ` M P I _ M P I C X X _ F O U N D ` `
V a r i a b l e i n d i c a t i n g w h e t h e r t h e M P I - 2 C + + b i n d i n g s a r e present ( introduced in MPI-2, removed with MPI-3 ) .
` ` M P I _ F o r t r a n _ H A V E _ F 7 7 _ H E A D E R ` `
T r u e i f t h e F o r t r a n 7 7 h e a d e r ` ` m p i f . h ` ` i s a v a i l a b l e .
` ` M P I _ F o r t r a n _ H A V E _ F 9 0 _ M O D U L E ` `
T r u e i f t h e F o r t r a n 9 0 m o d u l e ` ` m p i ` ` c a n b e u s e d f o r a c c e s s i n g MPI ( MPI-2 and higher only ) .
` ` M P I _ F o r t r a n _ H A V E _ F 0 8 _ M O D U L E ` `
T r u e i f t h e F o r t r a n 2 0 0 8 ` ` m p i _ f 0 8 ` ` i s a v a i l a b l e t o M P I programs ( MPI-3 and higher only ) .
I f p o s s i b l e , t h e M P I v e r s i o n w i l l b e d e t e r m i n e d b y t h i s m o d u l e . T h e f a c i l i t i e s t o d e t e c t t h e M P I v e r s i o n
w e r e i n t r o d u c e d w i t h M P I - 1 . 2 , a n d t h e r e f o r e c a n n o t b e f o u n d f o r o l d e r M P I v e r s i o n s .
` ` M P I _ < l a n g > _ V E R S I O N _ M A J O R ` `
M a j o r v e r s i o n o f M P I i m p l e m e n t e d f o r ` ` < l a n g > ` ` b y t h e M P I d i s t r i b u t i o n .
` ` M P I _ < l a n g > _ V E R S I O N _ M I N O R ` `
M i n o r v e r s i o n o f M P I i m p l e m e n t e d f o r ` ` < l a n g > ` ` b y t h e M P I d i s t r i b u t i o n .
` ` M P I _ < l a n g > _ V E R S I O N ` `
M P I v e r s i o n i m p l e m e n t e d f o r ` ` < l a n g > ` ` b y t h e M P I d i s t r i b u t i o n .
N o t e t h a t t h e r e ' s n o v a r i a b l e f o r t h e C b i n d i n g s b e i n g a c c e s s i b l e t h r o u g h ` ` m p i . h ` ` , s i n c e t h e M P I s t a n d a r d s
a l w a y s h a v e r e q u i r e d t h i s b i n d i n g t o w o r k i n b o t h C a n d C + + c o d e .
F o r r u n n i n g M P I p r o g r a m s , t h e m o d u l e s e t s t h e f o l l o w i n g v a r i a b l e s
` ` M P I E X E C _ E X E C U T A B L E ` `
E x e c u t a b l e f o r r u n n i n g M P I p r o g r a m s , i f s u c h e x i s t s .
` ` M P I E X E C _ N U M P R O C _ F L A G ` `
F l a g t o p a s s t o ` ` m p i e x e c ` ` b e f o r e g i v i n g i t t h e n u m b e r o f p r o c e s s o r s t o r u n o n .
` ` M P I E X E C _ M A X _ N U M P R O C S ` `
N u m b e r o f M P I p r o c e s s o r s t o u t i l i z e . D e f a u l t s t o t h e n u m b e r
o f p r o c e s s o r s d e t e c t e d o n t h e h o s t s y s t e m .
` ` M P I E X E C _ P R E F L A G S ` `
F l a g s t o p a s s t o ` ` m p i e x e c ` ` d i r e c t l y b e f o r e t h e e x e c u t a b l e t o r u n .
` ` M P I E X E C _ P O S T F L A G S ` `
F l a g s t o p a s s t o ` ` m p i e x e c ` ` a f t e r o t h e r f l a g s .
V a r i a b l e s f o r l o c a t i n g M P I
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
2023-11-01 06:34:31 +08:00
T h i s m o d u l e p e r f o r m s a f o u r s t e p s e a r c h f o r a n M P I i m p l e m e n t a t i o n :
2023-11-01 06:11:15 +08:00
2023-11-01 06:34:31 +08:00
1 . S e a r c h f o r ` ` M P I E X E C _ E X E C U T A B L E ` ` a n d , i f f o u n d , u s e i t s b a s e d i r e c t o r y .
2 . C h e c k i f t h e c o m p i l e r h a s M P I s u p p o r t b u i l t - i n . T h i s i s t h e c a s e i f t h e u s e r p a s s e d a
2023-11-01 06:11:15 +08:00
c o m p i l e r w r a p p e r a s ` ` C M A K E _ < L A N G > _ C O M P I L E R ` ` o r i f t h e y ' r e o n a C r a y s y s t e m .
2023-11-01 06:34:31 +08:00
3 . A t t e m p t t o f i n d a n M P I c o m p i l e r w r a p p e r a n d d e t e r m i n e t h e c o m p i l e r i n f o r m a t i o n f r o m i t .
4 . T r y t o f i n d a n M P I i m p l e m e n t a t i o n t h a t d o e s n o t s h i p s u c h a w r a p p e r b y g u e s s i n g s e t t i n g s .
2023-11-01 06:11:15 +08:00
C u r r e n t l y , o n l y M i c r o s o f t M P I a n d M P I C H 2 o n W i n d o w s a r e s u p p o r t e d .
2023-11-01 06:34:31 +08:00
F o r c o n t r o l l i n g t h e ` ` M P I E X E C _ E X E C U T A B L E ` ` s t e p , t h e f o l l o w i n g v a r i a b l e s m a y b e s e t :
` ` M P I E X E C _ E X E C U T A B L E ` `
M a n u a l l y s p e c i f y t h e l o c a t i o n o f ` ` m p i e x e c ` ` .
` ` M P I _ H O M E ` `
S p e c i f y t h e b a s e d i r e c t o r y o f t h e M P I i n s t a l l a t i o n .
` ` E N V { M P I _ H O M E } ` `
E n v i r o n m e n t v a r i a b l e t o s p e c i f y t h e b a s e d i r e c t o r y o f t h e M P I i n s t a l l a t i o n .
` ` E N V { I _ M P I _ R O O T } ` `
E n v i r o n m e n t v a r i a b l e t o s p e c i f y t h e b a s e d i r e c t o r y o f t h e M P I i n s t a l l a t i o n .
F o r c o n t r o l l i n g t h e c o m p i l e r w r a p p e r s t e p , t h e f o l l o w i n g v a r i a b l e s m a y b e s e t :
2023-11-01 06:11:15 +08:00
` ` M P I _ < l a n g > _ C O M P I L E R ` `
S e a r c h f o r t h e s p e c i f i e d c o m p i l e r w r a p p e r a n d u s e i t .
` ` M P I _ < l a n g > _ C O M P I L E R _ F L A G S ` `
F l a g s t o p a s s t o t h e M P I c o m p i l e r w r a p p e r d u r i n g i n t e r r o g a t i o n . S o m e c o m p i l e r w r a p p e r s
s u p p o r t l i n k i n g d e b u g o r t r a c i n g l i b r a r i e s i f a s p e c i f i c f l a g i s p a s s e d a n d t h i s v a r i a b l e
m a y b e u s e d t o o b t a i n t h e m .
` ` M P I _ C O M P I L E R _ F L A G S ` `
U s e d t o i n i t i a l i z e ` ` M P I _ < l a n g > _ C O M P I L E R _ F L A G S ` ` i f n o l a n g u a g e s p e c i f i c f l a g h a s b e e n g i v e n .
E m p t y b y d e f a u l t .
` ` M P I _ E X E C U T A B L E _ S U F F I X ` `
A s u f f i x w h i c h i s a p p e n d e d t o a l l n a m e s t h a t a r e b e i n g l o o k e d f o r . F o r i n s t a n c e y o u m a y s e t t h i s
t o ` ` . m p i c h ` ` o r ` ` . o p e n m p i ` ` t o p r e f e r t h e o n e o r t h e o t h e r o n D e b i a n a n d i t s d e r i v a t i v e s .
I n o r d e r t o c o n t r o l t h e g u e s s i n g s t e p , t h e f o l l o w i n g v a r i a b l e m a y b e s e t :
` ` M P I _ G U E S S _ L I B R A R Y _ N A M E ` `
V a l i d v a l u e s a r e ` ` M S M P I ` ` a n d ` ` M P I C H 2 ` ` . I f s e t , o n l y t h e g i v e n l i b r a r y w i l l b e s e a r c h e d f o r .
B y d e f a u l t , ` ` M S M P I ` ` w i l l b e p r e f e r r e d o v e r ` ` M P I C H 2 ` ` i f b o t h a r e a v a i l a b l e .
T h i s a l s o s e t s ` ` M P I _ S K I P _ C O M P I L E R _ W R A P P E R ` ` t o ` ` t r u e ` ` , w h i c h m a y b e o v e r r i d d e n .
E a c h o f t h e s e a r c h s t e p s m a y b e s k i p p e d w i t h t h e f o l l o w i n g c o n t r o l v a r i a b l e s :
` ` M P I _ A S S U M E _ N O _ B U I L T I N _ M P I ` `
I f t r u e , t h e m o d u l e a s s u m e s t h a t t h e c o m p i l e r i t s e l f d o e s n o t p r o v i d e a n M P I i m p l e m e n t a t i o n a n d
s k i p s t o s t e p 2 .
` ` M P I _ S K I P _ C O M P I L E R _ W R A P P E R ` `
I f t r u e , n o c o m p i l e r w r a p p e r w i l l b e s e a r c h e d f o r .
` ` M P I _ S K I P _ G U E S S I N G ` `
I f t r u e , t h e g u e s s i n g s t e p w i l l b e s k i p p e d .
A d d i t i o n a l l y , t h e f o l l o w i n g c o n t r o l v a r i a b l e i s a v a i l a b l e t o c h a n g e s e a r c h b e h a v i o r :
` ` M P I _ C X X _ S K I P _ M P I C X X ` `
A d d s o m e d e f i n i t i o n s t h a t w i l l d i s a b l e t h e M P I - 2 C + + b i n d i n g s .
C u r r e n t l y s u p p o r t e d a r e M P I C H , O p e n M P I , P l a t f o r m M P I a n d d e r i v a t i v e s t h e r e o f ,
f o r e x a m p l e M V A P I C H o r I n t e l M P I .
I f t h e f i n d p r o c e d u r e f a i l s f o r a v a r i a b l e ` ` M P I _ < l a n g > _ W O R K S ` ` , t h e n t h e s e t t i n g s d e t e c t e d b y o r p a s s e d t o
t h e m o d u l e d i d n o t w o r k a n d e v e n a s i m p l e M P I t e s t p r o g r a m f a i l e d t o c o m p i l e .
I f a l l o f t h e s e p a r a m e t e r s w e r e n o t s u f f i c i e n t t o f i n d t h e r i g h t M P I i m p l e m e n t a t i o n , a u s e r m a y
d i s a b l e t h e e n t i r e a u t o d e t e c t i o n p r o c e s s b y s p e c i f y i n g b o t h a l i s t o f l i b r a r i e s i n ` ` M P I _ < l a n g > _ L I B R A R I E S ` `
a n d a l i s t o f i n c l u d e d i r e c t o r i e s i n ` ` M P I _ < l a n g > _ A D D I T I O N A L _ I N C L U D E _ D I R S ` ` .
A n y o t h e r v a r i a b l e m a y b e s e t i n a d d i t i o n t o t h e s e t w o . T h e m o d u l e w i l l t h e n v a l i d a t e t h e M P I s e t t i n g s a n d s t o r e t h e
s e t t i n g s i n t h e c a c h e .
C a c h e v a r i a b l e s f o r M P I
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
T h e v a r i a b l e ` ` M P I _ < l a n g > _ I N C L U D E _ D I R S ` ` w i l l b e a s s e m b l e d f r o m t h e f o l l o w i n g v a r i a b l e s .
F o r C a n d C X X :
` ` M P I _ < l a n g > _ H E A D E R _ D I R ` `
L o c a t i o n o f t h e ` ` m p i . h ` ` h e a d e r o n d i s k .
F o r F o r t r a n :
` ` M P I _ F o r t r a n _ F 7 7 _ H E A D E R _ D I R ` `
L o c a t i o n o f t h e F o r t r a n 7 7 h e a d e r ` ` m p i f . h ` ` , i f i t e x i s t s .
` ` M P I _ F o r t r a n _ M O D U L E _ D I R ` `
L o c a t i o n o f t h e ` ` m p i ` ` o r ` ` m p i _ f 0 8 ` ` m o d u l e s , i f a v a i l a b l e .
F o r a l l l a n g u a g e s t h e f o l l o w i n g v a r i a b l e s a r e a d d i t i o n a l l y c o n s i d e r e d :
` ` M P I _ < l a n g > _ A D D I T I O N A L _ I N C L U D E _ D I R S ` `
A : r e f : ` ; - l i s t < C M a k e L a n g u a g e L i s t s > ` o f p a t h s n e e d e d i n a d d i t i o n t o t h e n o r m a l i n c l u d e d i r e c t o r i e s .
` ` M P I _ < i n c l u d e _ n a m e > _ I N C L U D E _ D I R ` `
P a t h v a r i a b l e s f o r i n c l u d e f o l d e r s r e f e r r e d t o b y ` ` < i n c l u d e _ n a m e > ` ` .
` ` M P I _ < l a n g > _ A D D I T I O N A L _ I N C L U D E _ V A R S ` `
A : r e f : ` ; - l i s t < C M a k e L a n g u a g e L i s t s > ` o f ` ` < i n c l u d e _ n a m e > ` ` t h a t w i l l b e a d d e d t o t h e i n c l u d e l o c a t i o n s o f ` ` < l a n g > ` ` .
T h e v a r i a b l e ` ` M P I _ < l a n g > _ L I B R A R I E S ` ` w i l l b e a s s e m b l e d f r o m t h e f o l l o w i n g v a r i a b l e s :
` ` M P I _ < l i b _ n a m e > _ L I B R A R Y ` `
T h e l o c a t i o n o f a l i b r a r y c a l l e d ` ` < l i b _ n a m e > ` ` f o r u s e w i t h M P I .
` ` M P I _ < l a n g > _ L I B _ N A M E S ` `
A : r e f : ` ; - l i s t < C M a k e L a n g u a g e L i s t s > ` o f ` ` < l i b _ n a m e > ` ` t h a t w i l l b e a d d e d t o t h e i n c l u d e l o c a t i o n s o f ` ` < l a n g > ` ` .
U s a g e o f m p i e x e c
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
W h e n u s i n g ` ` M P I E X E C _ E X E C U T A B L E ` ` t o e x e c u t e M P I a p p l i c a t i o n s , y o u s h o u l d t y p i c a l l y
u s e a l l o f t h e ` ` M P I E X E C _ E X E C U T A B L E ` ` f l a g s a s f o l l o w s :
: :
$ { M P I E X E C _ E X E C U T A B L E } $ { M P I E X E C _ N U M P R O C _ F L A G } $ { M P I E X E C _ M A X _ N U M P R O C S }
$ { M P I E X E C _ P R E F L A G S } E X E C U T A B L E $ { M P I E X E C _ P O S T F L A G S } A R G S
w h e r e ` ` E X E C U T A B L E ` ` i s t h e M P I p r o g r a m , a n d ` ` A R G S ` ` a r e t h e a r g u m e n t s t o
p a s s t o t h e M P I p r o g r a m .
A d v a n c e d v a r i a b l e s f o r u s i n g M P I
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
T h e m o d u l e c a n p e r f o r m s o m e a d v a n c e d f e a t u r e d e t e c t i o n s u p o n e x p l i c i t r e q u e s t .
* * I m p o r t a n t n o t i c e : * * T h e f o l l o w i n g c h e c k s c a n n o t b e p e r f o r m e d w i t h o u t * e x e c u t i n g * a n M P I t e s t p r o g r a m .
C o n s i d e r t h e s p e c i a l c o n s i d e r a t i o n s f o r t h e b e h a v i o r o f : c o m m a n d : ` t r y _ r u n ` d u r i n g c r o s s c o m p i l a t i o n .
M o r e o v e r , r u n n i n g a n M P I p r o g r a m c a n c a u s e a d d i t i o n a l i s s u e s , l i k e a f i r e w a l l n o t i f i c a t i o n o n s o m e s y s t e m s .
Y o u s h o u l d o n l y e n a b l e t h e s e d e t e c t i o n s i f y o u a b s o l u t e l y n e e d t h e i n f o r m a t i o n .
I f t h e f o l l o w i n g v a r i a b l e s a r e s e t t o t r u e , t h e r e s p e c t i v e s e a r c h w i l l b e p e r f o r m e d :
` ` M P I _ D E T E R M I N E _ F o r t r a n _ C A P A B I L I T I E S ` `
D e t e r m i n e f o r a l l a v a i l a b l e F o r t r a n b i n d i n g s w h a t t h e v a l u e s o f ` ` M P I _ S U B A R R A Y S _ S U P P O R T E D ` ` a n d
` ` M P I _ A S Y N C _ P R O T E C T S _ N O N B L O C K I N G ` ` a r e a n d m a k e t h e i r v a l u e s a v a i l a b l e a s ` ` M P I _ F o r t r a n _ < b i n d i n g > _ S U B A R R A Y S ` `
a n d ` ` M P I _ F o r t r a n _ < b i n d i n g > _ A S Y N C P R O T ` ` , w h e r e ` ` < b i n d i n g > ` ` i s o n e o f ` ` F 7 7 _ H E A D E R ` ` , ` ` F 9 0 _ M O D U L E ` ` a n d
` ` F 0 8 _ M O D U L E ` ` .
` ` M P I _ D E T E R M I N E _ L I B R A R Y _ V E R S I O N ` `
2023-11-01 06:20:22 +08:00
F o r e a c h l a n g u a g e , f i n d t h e o u t p u t o f ` ` M P I _ G e t _ l i b r a r y _ v e r s i o n ` ` a n d m a k e i t a v a i l a b l e a s ` ` M P I _ < l a n g > _ L I B R A R Y _ V E R S I O N _ S T R I N G ` ` .
2023-11-01 06:11:15 +08:00
T h i s i n f o r m a t i o n i s u s u a l l y t i e d t o t h e r u n t i m e c o m p o n e n t o f a n M P I i m p l e m e n t a t i o n a n d m i g h t d i f f e r d e p e n d i n g o n ` ` < l a n g > ` ` .
N o t e t h a t t h e r e t u r n v a l u e i s e n t i r e l y i m p l e m e n t a t i o n d e f i n e d . T h i s i n f o r m a t i o n m i g h t b e u s e d t o i d e n t i f y
t h e M P I v e n d o r a n d f o r e x a m p l e p i c k t h e c o r r e c t o n e o f m u l t i p l e t h i r d p a r t y b i n a r i e s t h a t m a t c h e s t h e M P I v e n d o r .
B a c k w a r d C o m p a t i b i l i t y
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
F o r b a c k w a r d c o m p a t i b i l i t y w i t h o l d e r v e r s i o n s o f F i n d M P I , t h e s e
v a r i a b l e s a r e s e t , b u t d e p r e c a t e d :
: :
M P I _ C O M P I L E R M P I _ L I B R A R Y M P I _ E X T R A _ L I B R A R Y
M P I _ C O M P I L E _ F L A G S M P I _ I N C L U D E _ P A T H M P I _ L I N K _ F L A G S
M P I _ L I B R A R I E S
I n n e w p r o j e c t s , p l e a s e u s e t h e ` ` M P I _ < l a n g > _ X X X ` ` e q u i v a l e n t s .
A d d i t i o n a l l y , t h e f o l l o w i n g v a r i a b l e s a r e d e p r e c a t e d :
` ` M P I _ < l a n g > _ C O M P I L E _ F L A G S ` `
U s e ` ` M P I _ < l a n g > _ C O M P I L E _ O P T I O N S ` ` a n d ` ` M P I _ < l a n g > _ C O M P I L E _ D E F I N I T I O N S ` ` i n s t e a d .
` ` M P I _ < l a n g > _ I N C L U D E _ P A T H ` `
F o r c o n s u m p t i o n u s e ` ` M P I _ < l a n g > _ I N C L U D E _ D I R S ` ` a n d f o r s p e c i f y i n g f o l d e r s u s e ` ` M P I _ < l a n g > _ A D D I T I O N A L _ I N C L U D E _ D I R S ` ` i n s t e a d .
` ` M P I E X E C ` `
U s e ` ` M P I E X E C _ E X E C U T A B L E ` ` i n s t e a d .
#]=======================================================================]
cmake_policy ( PUSH )
cmake_policy ( SET CMP0057 NEW ) # if IN_LIST
include ( ${ CMAKE_CURRENT_LIST_DIR } /FindPackageHandleStandardArgs.cmake )
# Generic compiler names
set ( _MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r )
set ( _MPI_CXX_GENERIC_COMPILER_NAMES mpicxx mpiCC mpcxx mpCC mpic++ mpc++
m p i c x x _ r m p i C C _ r m p c x x _ r m p C C _ r m p i c + + _ r m p c + + _ r )
set ( _MPI_Fortran_GENERIC_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r
m p i f 9 0 m p i f 9 0 _ r m p f 9 0 m p f 9 0 _ r
m p i f 7 7 m p i f 7 7 _ r m p f 7 7 m p f 7 7 _ r
m p i f c )
# GNU compiler names
set ( _MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r )
set ( _MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r mpigxx )
set ( _MPI_GNU_Fortran_COMPILER_NAMES mpigfortran mpgfortran mpigfortran_r mpgfortran_r
m p i g 7 7 m p i g 7 7 _ r m p g 7 7 m p g 7 7 _ r )
# Intel MPI compiler names on Windows
if ( WIN32 )
list ( APPEND _MPI_C_GENERIC_COMPILER_NAMES mpicc.bat )
list ( APPEND _MPI_CXX_GENERIC_COMPILER_NAMES mpicxx.bat )
list ( APPEND _MPI_Fortran_GENERIC_COMPILER_NAMES mpifc.bat )
# Intel MPI compiler names
set ( _MPI_Intel_C_COMPILER_NAMES mpiicc.bat )
set ( _MPI_Intel_CXX_COMPILER_NAMES mpiicpc.bat )
set ( _MPI_Intel_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat )
# Intel MPI compiler names for MSMPI
set ( _MPI_MSVC_C_COMPILER_NAMES mpicl.bat )
set ( _MPI_MSVC_CXX_COMPILER_NAMES mpicl.bat )
else ( )
# Intel compiler names
set ( _MPI_Intel_C_COMPILER_NAMES mpiicc )
set ( _MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++ )
set ( _MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77 )
endif ( )
# PGI compiler names
2023-11-01 06:34:31 +08:00
set ( _MPI_PGI_C_COMPILER_NAMES mpipgicc mpipgcc mppgcc )
set ( _MPI_PGI_CXX_COMPILER_NAMES mpipgic++ mpipgCC mppgCC )
set ( _MPI_PGI_Fortran_COMPILER_NAMES mpipgifort mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77 )
2023-11-01 06:11:15 +08:00
# XLC MPI Compiler names
set ( _MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r )
set ( _MPI_XL_CXX_COMPILER_NAMES mpixlcxx mpixlC mpixlc++ mpxlcxx mpxlc++ mpixlc++ mpxlCC
m p i x l c x x _ r m p i x l C _ r m p i x l c + + _ r m p x l c x x _ r m p x l c + + _ r m p i x l c + + _ r m p x l C C _ r )
set ( _MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95_r
m p i x l f 9 0 m p i x l f 9 0 _ r m p x l f 9 0 m p x l f 9 0 _ r
m p i x l f 7 7 m p i x l f 7 7 _ r m p x l f 7 7 m p x l f 7 7 _ r
m p i x l f m p i x l f _ r m p x l f m p x l f _ r )
# Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler,
# attempt all of them.
# By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper
# stems from a proprietary MPI and won't know which compiler it's being used for. For instance, Intel MPI
# controls its settings via the I_MPI_CC environment variables if the generic name is being used.
# If we know which compiler we're working with, we can use the most specialized wrapper there is in order to
# pick up the right settings for it.
foreach ( LANG IN ITEMS C CXX Fortran )
set ( _MPI_ ${ LANG } _COMPILER_NAMES "" )
foreach ( id IN ITEMS GNU Intel MSVC PGI XL )
if ( NOT CMAKE_ ${ LANG } _COMPILER_ID OR CMAKE_ ${ LANG } _COMPILER_ID STREQUAL id )
2023-11-01 06:20:22 +08:00
foreach ( _COMPILER_NAME IN LISTS _MPI_ ${ id } _ ${ LANG } _COMPILER_NAMES )
list ( APPEND _MPI_ ${ LANG } _COMPILER_NAMES ${ _COMPILER_NAME } ${ MPI_EXECUTABLE_SUFFIX } )
endforeach ( )
2023-11-01 06:11:15 +08:00
endif ( )
unset ( _MPI_ ${ id } _ ${ LANG } _COMPILER_NAMES )
endforeach ( )
2023-11-01 06:20:22 +08:00
foreach ( _COMPILER_NAME IN LISTS _MPI_ ${ LANG } _GENERIC_COMPILER_NAMES )
list ( APPEND _MPI_ ${ LANG } _COMPILER_NAMES ${ _COMPILER_NAME } ${ MPI_EXECUTABLE_SUFFIX } )
endforeach ( )
2023-11-01 06:11:15 +08:00
unset ( _MPI_ ${ LANG } _GENERIC_COMPILER_NAMES )
endforeach ( )
# Names to try for mpiexec
# Only mpiexec commands are guaranteed to behave as described in the standard,
# mpirun commands are not covered by the standard in any way whatsoever.
# lamexec is the executable for LAM/MPI, srun is for SLURM or Open MPI with SLURM support.
# srun -n X <executable> is however a valid command, so it behaves 'like' mpiexec.
set ( _MPIEXEC_NAMES_BASE mpiexec mpiexec.hydra mpiexec.mpd mpirun lamexec srun )
unset ( _MPIEXEC_NAMES )
foreach ( _MPIEXEC_NAME IN LISTS _MPIEXEC_NAMES_BASE )
list ( APPEND _MPIEXEC_NAMES "${_MPIEXEC_NAME}${MPI_EXECUTABLE_SUFFIX}" )
endforeach ( )
unset ( _MPIEXEC_NAMES_BASE )
function ( _MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE )
if ( DEFINED MPI_ ${ LANG } _COMPILER_FLAGS )
separate_arguments ( _MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_${LANG}_COMPILER_FLAGS}" )
else ( )
separate_arguments ( _MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_COMPILER_FLAGS}" )
endif ( )
execute_process (
C O M M A N D $ { M P I _ $ { L A N G } _ C O M P I L E R } $ { _ M P I _ C O M P I L E R _ W R A P P E R _ O P T I O N S } $ { Q U E R Y _ F L A G }
O U T P U T _ V A R I A B L E W R A P P E R _ O U T P U T O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ V A R I A B L E W R A P P E R _ O U T P U T E R R O R _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
R E S U L T _ V A R I A B L E W R A P P E R _ R E T U R N )
# Some compiler wrappers will yield spurious zero return values, for example
# Intel MPI tolerates unknown arguments and if the MPI wrappers loads a shared
# library that has invalid or missing version information there would be warning
# messages emitted by ld.so in the compiler output. In either case, we'll treat
# the output as invalid.
if ( "${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found" )
set ( WRAPPER_RETURN 255 )
endif ( )
# Ensure that no error output might be passed upwards.
if ( NOT WRAPPER_RETURN EQUAL 0 )
unset ( WRAPPER_OUTPUT )
else ( )
# Strip leading whitespace
string ( REGEX REPLACE "^ +" "" WRAPPER_OUTPUT "${WRAPPER_OUTPUT}" )
endif ( )
set ( ${ OUTPUT_VARIABLE } "${WRAPPER_OUTPUT}" PARENT_SCOPE )
set ( ${ RESULT_VARIABLE } "${WRAPPER_RETURN}" PARENT_SCOPE )
endfunction ( )
macro ( _MPI_env_set_ifnot VAR VALUE )
if ( NOT DEFINED ENV{ ${ VAR } } )
set ( _MPI_ ${ VAR } _WAS_SET FALSE )
set ( ENV{ ${ VAR } } ${ ${VALUE } } )
else ( )
set ( _MPI_ ${ VAR } _WAS_SET TRUE )
endif ( )
endmacro ( )
macro ( _MPI_env_unset_ifnot VAR )
if ( NOT _MPI_ ${ VAR } _WAS_SET )
unset ( ENV{ ${ VAR } } )
endif ( )
endmacro ( )
function ( _MPI_interrogate_compiler LANG )
unset ( MPI_COMPILE_CMDLINE )
unset ( MPI_LINK_CMDLINE )
unset ( MPI_COMPILE_OPTIONS_WORK )
unset ( MPI_COMPILE_DEFINITIONS_WORK )
unset ( MPI_INCLUDE_DIRS_WORK )
unset ( MPI_LINK_FLAGS_WORK )
unset ( MPI_LIB_NAMES_WORK )
unset ( MPI_LIB_FULLPATHS_WORK )
# Define the MPICH and Intel MPI compiler variables to the compilers set in CMake.
# It's possible to have a per-compiler configuration in these MPI implementations and
# a particular MPICH derivate might check compiler interoperability.
# Intel MPI in particular does this with I_MPI_CHECK_COMPILER.
file ( TO_NATIVE_PATH "${CMAKE_${LANG}_COMPILER}" _MPI_UNDERLAYING_COMPILER )
# On Windows, the Intel MPI batch scripts can only work with filnames - Full paths will break them.
# Due to the lack of other MPICH-based wrappers for Visual C++, we may treat this as default.
if ( MSVC )
get_filename_component ( _MPI_UNDERLAYING_COMPILER "${_MPI_UNDERLAYING_COMPILER}" NAME )
endif ( )
if ( "${LANG}" STREQUAL "C" )
_MPI_env_set_ifnot ( I_MPI_CC _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( MPICH_CC _MPI_UNDERLAYING_COMPILER )
elseif ( "${LANG}" STREQUAL "CXX" )
_MPI_env_set_ifnot ( I_MPI_CXX _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( MPICH_CXX _MPI_UNDERLAYING_COMPILER )
elseif ( "${LANG}" STREQUAL "Fortran" )
_MPI_env_set_ifnot ( I_MPI_FC _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( MPICH_FC _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( I_MPI_F77 _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( MPICH_F77 _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( I_MPI_F90 _MPI_UNDERLAYING_COMPILER )
_MPI_env_set_ifnot ( MPICH_F90 _MPI_UNDERLAYING_COMPILER )
endif ( )
# Set these two variables for Intel MPI:
# - I_MPI_DEBUG_INFO_STRIP: It adds 'objcopy' lines to the compiler output. We support stripping them
# (see below), but if we can avoid them in the first place, we should.
# - I_MPI_FORT_BIND: By default Intel MPI makes the C/C++ compiler wrappers link Fortran bindings.
# This is so that mixed-language code doesn't require additional libraries when linking with mpicc.
# For our purposes, this makes little sense, since correct MPI usage from CMake already circumvenes this.
set ( _MPI_ENV_VALUE "disable" )
_MPI_env_set_ifnot ( I_MPI_DEBUG_INFO_STRIP _MPI_ENV_VALUE )
_MPI_env_set_ifnot ( I_MPI_FORT_BIND _MPI_ENV_VALUE )
# Check whether the -showme:compile option works. This indicates that we have either Open MPI
# or a newer version of LAM/MPI, and implies that -showme:link will also work.
# Open MPI also supports -show, but separates linker and compiler information
_MPI_check_compiler ( ${ LANG } "-showme:compile" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN )
if ( MPI_COMPILER_RETURN EQUAL 0 )
_MPI_check_compiler ( ${ LANG } "-showme:link" MPI_LINK_CMDLINE MPI_COMPILER_RETURN )
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
unset ( MPI_COMPILE_CMDLINE )
endif ( )
endif ( )
# MPICH and MVAPICH offer -compile-info and -link-info.
# For modern versions, both do the same as -show. However, for old versions, they do differ
# when called for mpicxx and mpif90 and it's necessary to use them over -show in order to find the
# removed MPI C++ bindings.
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
_MPI_check_compiler ( ${ LANG } "-compile-info" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN )
if ( MPI_COMPILER_RETURN EQUAL 0 )
_MPI_check_compiler ( ${ LANG } "-link-info" MPI_LINK_CMDLINE MPI_COMPILER_RETURN )
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
unset ( MPI_COMPILE_CMDLINE )
endif ( )
endif ( )
endif ( )
# MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the
# -showme commands are more specialized.
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
_MPI_check_compiler ( ${ LANG } "-show" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN )
endif ( )
# Older versions of LAM/MPI have "-showme". Open MPI also supports this.
# Unknown to MPICH, MVAPICH and Intel MPI.
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
_MPI_check_compiler ( ${ LANG } "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN )
endif ( )
if ( MPI_COMPILER_RETURN EQUAL 0 AND DEFINED MPI_COMPILE_CMDLINE )
# Intel MPI can be run with -compchk or I_MPI_CHECK_COMPILER set to 1.
# In this case, -show will be prepended with a line to the compiler checker. This is a script that performs
# compatibility checks and returns a non-zero exit code together with an error if something fails.
# It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64).
# The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler.
# NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler.
if ( "${MPI_COMPILE_CMDLINE}" MATCHES "^([^\" ]+/compchk.sh|\ "[^\" ]+/compchk.sh\ ") +([^ ]+)" )
# Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag.
unset ( COMPILER_CHECKER_OUTPUT )
execute_process (
C O M M A N D $ { C M A K E _ M A T C H _ 1 } $ { C M A K E _ M A T C H _ 2 } $ { M P I _ $ { L A N G } _ C O M P I L E R }
O U T P U T _ V A R I A B L E C O M P I L E R _ C H E C K E R _ O U T P U T O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
E R R O R _ V A R I A B L E C O M P I L E R _ C H E C K E R _ O U T P U T E R R O R _ S T R I P _ T R A I L I N G _ W H I T E S P A C E
R E S U L T _ V A R I A B L E M P I _ C O M P I L E R _ R E T U R N )
# If it returned a non-zero value, the check below will fail and cause the interrogation to be aborted.
if ( NOT MPI_COMPILER_RETURN EQUAL 0 )
if ( NOT MPI_FIND_QUIETLY )
message ( STATUS "Intel MPI compiler check failed: ${COMPILER_CHECKER_OUTPUT}" )
endif ( )
else ( )
# Since the check passed, we can remove the compchk.sh script.
string ( REGEX REPLACE "^([^\" ]+|\ "[^\" ]+\ ")/compchk.sh.*\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}" )
endif ( )
endif ( )
endif ( )
# Revert changes to the environment made previously
if ( "${LANG}" STREQUAL "C" )
_MPI_env_unset_ifnot ( I_MPI_CC )
_MPI_env_unset_ifnot ( MPICH_CC )
elseif ( "${LANG}" STREQUAL "CXX" )
_MPI_env_unset_ifnot ( I_MPI_CXX )
_MPI_env_unset_ifnot ( MPICH_CXX )
elseif ( "${LANG}" STREQUAL "Fortran" )
_MPI_env_unset_ifnot ( I_MPI_FC )
_MPI_env_unset_ifnot ( MPICH_FC )
_MPI_env_unset_ifnot ( I_MPI_F77 )
_MPI_env_unset_ifnot ( MPICH_F77 )
_MPI_env_unset_ifnot ( I_MPI_F90 )
_MPI_env_unset_ifnot ( MPICH_F90 )
endif ( )
_MPI_env_unset_ifnot ( I_MPI_DEBUG_INFO_STRIP )
_MPI_env_unset_ifnot ( I_MPI_FORT_BIND )
if ( NOT ( MPI_COMPILER_RETURN EQUAL 0 ) OR NOT ( DEFINED MPI_COMPILE_CMDLINE ) )
# Cannot interrogate this compiler, so exit.
set ( MPI_ ${ LANG } _WRAPPER_FOUND FALSE PARENT_SCOPE )
return ( )
endif ( )
unset ( MPI_COMPILER_RETURN )
# We have our command lines, but we might need to copy MPI_COMPILE_CMDLINE
# into MPI_LINK_CMDLINE, if we didn't find the link line.
if ( NOT DEFINED MPI_LINK_CMDLINE )
set ( MPI_LINK_CMDLINE "${MPI_COMPILE_CMDLINE}" )
endif ( )
# Visual Studio parsers permit each flag prefixed by either / or -.
# We'll normalize this to the - syntax we use for CMake purposes anyways.
if ( MSVC )
foreach ( _MPI_VARIABLE IN ITEMS COMPILE LINK )
# The Intel MPI wrappers on Windows prefix their output with some copyright boilerplate.
# To prevent possible problems, we discard this text before proceeding with any further matching.
string ( REGEX REPLACE "^[^ ]+ for the Intel\\(R\\) MPI Library [^\n]+ for Windows\\*\nCopyright\\(C\\) [^\n]+, Intel Corporation\\. All rights reserved\\.\n\n" ""
M P I _ $ { _ M P I _ V A R I A B L E } _ C M D L I N E " $ { M P I _ $ { _ M P I _ V A R I A B L E } _ C M D L I N E } " )
string ( REGEX REPLACE "(^| )/" "\\1-" MPI_ ${ _MPI_VARIABLE } _CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}" )
string ( REPLACE "-libpath:" "-LIBPATH:" MPI_ ${ _MPI_VARIABLE } _CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}" )
endforeach ( )
endif ( )
# For MSVC and cl-compatible compilers, the keyword /link indicates a point after which
# everything following is passed to the linker. In this case, we drop all prior information
# from the link line and treat any unknown extra flags as linker flags.
set ( _MPI_FILTERED_LINK_INFORMATION FALSE )
if ( MSVC )
if ( MPI_LINK_CMDLINE MATCHES " -(link|LINK) " )
string ( REGEX REPLACE ".+-(link|LINK) +" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}" )
set ( _MPI_FILTERED_LINK_INFORMATION TRUE )
endif ( )
string ( REGEX REPLACE " +-(link|LINK) .+" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}" )
endif ( )
if ( UNIX )
# At this point, we obtained some output from a compiler wrapper that works.
# We'll now try to parse it into variables with meaning to us.
if ( "${LANG}" STREQUAL "Fortran" )
# If MPICH (and derivates) didn't recognize the Fortran compiler include flag during configuration,
# they'll return a set of three commands, consisting out of a symlink command for mpif.h,
# the actual compiler command and deletion of the created symlink.
# Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate
# this output into an additional include directory and then drop it from the output.
if ( "${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\ "[^\" ]+\ ") mpif.h" )
get_filename_component ( MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY )
string ( REGEX REPLACE "^ln -s ([^\" ]+|\ "[^\" ]+\ ") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}" )
string ( REGEX REPLACE "^ln -s ([^\" ]+|\ "[^\" ]+\ ") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}" )
string ( REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}" )
string ( REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}" )
endif ( )
endif ( )
# If Intel MPI was configured for static linkage with -static_mpi, the wrapper will by default strip
# debug information from resulting binaries (see I_MPI_DEBUG_INFO_STRIP).
# Since we cannot process this information into CMake logic, we need to discard the resulting objcopy
# commands from the output.
string ( REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}" )
string ( REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}" )
endif ( )
# For Visual C++, extracting compiler options in a generic fashion isn't easy. However, no MPI implementation
# on Windows seems to require any specific ones, either.
if ( NOT MSVC )
# Extract compile options from the compile command line.
string ( REGEX MATCHALL "(^| )-f([^\" ]+|\ "[^\" ]+\ ")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}" )
foreach ( _MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS )
string ( REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}" )
# Ignore -fstack-protector directives: These occur on MPICH and MVAPICH when the libraries
# themselves were built with this flag. However, this flag is unrelated to using MPI, and
# we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore
# produce inconsistent results with the regularly flags.
# Similarly, aliasing flags do not belong into our flag array.
if ( NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce])" )
list ( APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}" )
endif ( )
endforeach ( )
endif ( )
# For GNU-style compilers, it's possible to prefix includes and definitions with certain flags to pass them
# only to the preprocessor. For CMake purposes, we need to treat, but ignore such scopings.
# Note that we do not support spaces between the arguments, i.e. -Wp,-I -Wp,/opt/mympi will not be parsed
# correctly. This form does not seem to occur in any common MPI implementation, however.
if ( NOT MSVC )
set ( _MPI_PREPROCESSOR_FLAG_REGEX "(-Wp,|-Xpreprocessor )?" )
else ( )
set ( _MPI_PREPROCESSOR_FLAG_REGEX "" )
endif ( )
# Same deal as above, for the definitions.
string ( REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}-D *([^\" ]+|\ "[^\" ]+\ ")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}" )
foreach ( _MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS )
string ( REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}" )
string ( REPLACE "\" " " " _MPI_COMPILE_DEFINITION " ${ _MPI_COMPILE_DEFINITION } " )
if ( NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*" )
list ( APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}" )
endif ( )
endforeach ( )
# Extract include paths from compile command line
string ( REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *([^\" ]+|\ "[^\" ]+\ ")"
M P I _ A L L _ I N C L U D E _ P A T H S " $ { M P I _ C O M P I L E _ C M D L I N E } " )
# If extracting failed to work, we'll try using -showme:incdirs.
# Unlike before, we do this without the environment variables set up, but since only MPICH derivates are affected by any of them, and
# -showme:... is only supported by Open MPI and LAM/MPI, this isn't a concern.
if ( NOT MPI_ALL_INCLUDE_PATHS )
_MPI_check_compiler ( ${ LANG } "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN )
if ( MPI_INCDIRS_COMPILER_RETURN )
separate_arguments ( MPI_ALL_INCLUDE_PATHS NATIVE_COMMAND "${MPI_INCDIRS_CMDLINE}" )
endif ( )
endif ( )
foreach ( _MPI_INCLUDE_PATH IN LISTS MPI_ALL_INCLUDE_PATHS )
string ( REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}" )
string ( REPLACE "\" " " " _MPI_INCLUDE_PATH " ${ _MPI_INCLUDE_PATH } " )
get_filename_component ( _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}" REALPATH )
list ( APPEND MPI_INCLUDE_DIRS_WORK "${_MPI_INCLUDE_PATH}" )
endforeach ( )
# The next step are linker flags and library directories. Here, we first take the flags given in raw -L or -LIBPATH: syntax.
string ( REGEX MATCHALL "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\ "[^\" ]+\ ")" MPI_DIRECT_LINK_PATHS "${MPI_LINK_CMDLINE}" )
foreach ( _MPI_LPATH IN LISTS MPI_DIRECT_LINK_PATHS )
string ( REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *" "" _MPI_LPATH "${_MPI_LPATH}" )
list ( APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}" )
endforeach ( )
# If the link commandline hasn't been filtered (e.g. when using MSVC and /link), we need to extract the relevant parts first.
if ( NOT _MPI_FILTERED_LINK_INFORMATION )
string ( REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\ "[^\" ]+\ ")" MPI_LINK_FLAGS "${MPI_LINK_CMDLINE}" )
# In this case, we could also find some indirectly given linker paths, e.g. prefixed by -Xlinker or -Wl,
# Since syntaxes like -Wl,-L -Wl,/my/path/to/lib are also valid, we parse these paths by first removing -Wl, and -Xlinker
# from the list of filtered flags and then parse the remainder of the output.
string ( REGEX REPLACE "(-Wl,|-Xlinker +)" "" MPI_LINK_FLAGS_RAW "${MPI_LINK_FLAGS}" )
# Now we can parse the leftover output. Note that spaces can now be handled since the above example would reduce to
# -L /my/path/to/lib and can be extracted correctly.
string ( REGEX MATCHALL "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)([^\" ]+|\ "[^\" ]+\ ")"
M P I _ I N D I R E C T _ L I N K _ P A T H S " $ { M P I _ L I N K _ F L A G S _ R A W } " )
foreach ( _MPI_LPATH IN LISTS MPI_INDIRECT_LINK_PATHS )
string ( REGEX REPLACE "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)" "" _MPI_LPATH "${_MPI_LPATH}" )
list ( APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}" )
endforeach ( )
# We need to remove the flags we extracted from the linker flag list now.
string ( REGEX REPLACE "(^| )(-Wl,|-Xlinker +)(${CMAKE_LIBRARY_PATH_FLAG},? *(-Wl,|-Xlinker +)?|--library-path=)([^\" ]+|\ "[^\" ]+\ ")" ""
M P I _ L I N K _ C M D L I N E _ F I L T E R E D " $ { M P I _ L I N K _ C M D L I N E } " )
# Some MPI implementations pass on options they themselves were built with. Since -z,noexecstack is a common
# hardening, we should strip it. In general, the -z options should be undesirable.
string ( REGEX REPLACE "(^| )-Wl,-z(,[^ ]+| +-Wl,[^ ]+)" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}" )
string ( REGEX REPLACE "(^| )-Xlinker +-z +-Xlinker +[^ ]+" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}" )
# We only consider options of the form -Wl or -Xlinker:
string ( REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\ "[^\" ]+\ ")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE_FILTERED}" )
# As a next step, we assemble the linker flags extracted in a preliminary flags string
foreach ( _MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS )
string ( STRIP "${_MPI_LINK_FLAG}" _MPI_LINK_FLAG )
if ( MPI_LINK_FLAGS_WORK )
string ( APPEND MPI_LINK_FLAGS_WORK " ${_MPI_LINK_FLAG}" )
else ( )
set ( MPI_LINK_FLAGS_WORK "${_MPI_LINK_FLAG}" )
endif ( )
endforeach ( )
else ( )
# In the filtered case, we obtain the link time flags by just stripping the library paths.
string ( REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\ "[^\" ]+\ ")" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}" )
endif ( )
# If we failed to extract any linker paths, we'll try using the -showme:libdirs option with the MPI compiler.
# This will return a list of folders, not a set of flags!
if ( NOT MPI_ALL_LINK_PATHS )
_MPI_check_compiler ( ${ LANG } "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN )
if ( MPI_LIBDIRS_COMPILER_RETURN )
separate_arguments ( MPI_ALL_LINK_PATHS NATIVE_COMMAND "${MPI_LIBDIRS_CMDLINE}" )
endif ( )
endif ( )
# We need to remove potential quotes and convert the paths to CMake syntax while resolving them, too.
foreach ( _MPI_LPATH IN LISTS MPI_ALL_LINK_PATHS )
string ( REPLACE "\" " " " _MPI_LPATH " ${ _MPI_LPATH } " )
get_filename_component ( _MPI_LPATH "${_MPI_LPATH}" REALPATH )
list ( APPEND MPI_LINK_DIRECTORIES_WORK "${_MPI_LPATH}" )
endforeach ( )
# Extract the set of libraries to link against from the link command line
# This only makes sense if CMAKE_LINK_LIBRARY_FLAG is defined, i.e. a -lxxxx syntax is supported by the compiler.
if ( CMAKE_LINK_LIBRARY_FLAG )
string ( REGEX MATCHALL "(^| )${CMAKE_LINK_LIBRARY_FLAG}([^\" ]+|\ "[^\" ]+\ ")"
M P I _ L I B N A M E S " $ { M P I _ L I N K _ C M D L I N E } " )
foreach ( _MPI_LIB_NAME IN LISTS MPI_LIBNAMES )
string ( REGEX REPLACE "^ ?${CMAKE_LINK_LIBRARY_FLAG}" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}" )
string ( REPLACE "\" " " " _MPI_LIB_NAME " ${ _MPI_LIB_NAME } " )
list ( APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}" )
endforeach ( )
endif ( )
# Treat linker objects given by full path, for example static libraries, import libraries
# or shared libraries if there aren't any import libraries in use on the system.
# Note that we do not consider CMAKE_<TYPE>_LIBRARY_PREFIX intentionally here: The linker will for a given file
# decide how to link it based on file type, not based on a prefix like 'lib'.
set ( _MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}" )
if ( DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX )
if ( NOT ( "${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}" ) )
string ( APPEND _MPI_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}" )
endif ( )
else ( )
string ( APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}" )
endif ( )
set ( _MPI_LIB_NAME_REGEX "(([^\" ]+( ${ _MPI_LIB_SUFFIX_REGEX } ) ) | ( \ " [ ^ \ " ] + ( $ { _ M P I _ L I B _ S U F F I X _ R E G E X } ) \ " ) ) ( + | $ ) " )
string ( REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}" )
string ( REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}" )
foreach ( _MPI_LIB_NAME IN LISTS MPI_LIBNAMES )
string ( REGEX REPLACE "^ +\" ?|\ "? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}" )
get_filename_component ( _MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY )
if ( NOT "${_MPI_LIB_PATH}" STREQUAL "" )
list ( APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}" )
else ( )
list ( APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}" )
endif ( )
endforeach ( )
# Save the explicitly given link directories
set ( MPI_LINK_DIRECTORIES_LEFTOVER "${MPI_LINK_DIRECTORIES_WORK}" )
# An MPI compiler wrapper could have its MPI libraries in the implictly
# linked directories of the compiler itself.
if ( DEFINED CMAKE_ ${ LANG } _IMPLICIT_LINK_DIRECTORIES )
list ( APPEND MPI_LINK_DIRECTORIES_WORK "${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}" )
endif ( )
# Determine full path names for all of the libraries that one needs
# to link against in an MPI program
unset ( MPI_PLAIN_LIB_NAMES_WORK )
foreach ( _MPI_LIB_NAME IN LISTS MPI_LIB_NAMES_WORK )
get_filename_component ( _MPI_PLAIN_LIB_NAME "${_MPI_LIB_NAME}" NAME_WE )
list ( APPEND MPI_PLAIN_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}" )
find_library ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY
N A M E S " $ { _ M P I _ L I B _ N A M E } " " l i b $ { _ M P I _ L I B _ N A M E } "
H I N T S $ { M P I _ L I N K _ D I R E C T O R I E S _ W O R K }
D O C " L o c a t i o n o f t h e $ { _ M P I _ P L A I N _ L I B _ N A M E } l i b r a r y f o r M P I "
)
mark_as_advanced ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY )
# Remove the directory from the remainder list.
if ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY )
get_filename_component ( _MPI_TAKEN_DIRECTORY "${MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY}" DIRECTORY )
list ( REMOVE_ITEM MPI_LINK_DIRECTORIES_LEFTOVER "${_MPI_TAKEN_DIRECTORY}" )
endif ( )
endforeach ( )
# Add the link directories given explicitly that we haven't used back as linker directories.
2023-11-01 06:20:22 +08:00
if ( NOT WIN32 )
foreach ( _MPI_LINK_DIRECTORY IN LISTS MPI_LINK_DIRECTORIES_LEFTOVER )
file ( TO_NATIVE_PATH "${_MPI_LINK_DIRECTORY}" _MPI_LINK_DIRECTORY_ACTUAL )
string ( FIND "${_MPI_LINK_DIRECTORY_ACTUAL}" " " _MPI_LINK_DIRECTORY_CONTAINS_SPACE )
if ( NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL -1 )
set ( _MPI_LINK_DIRECTORY_ACTUAL "\" ${ _MPI_LINK_DIRECTORY_ACTUAL } \"")
endif ( )
if ( MPI_LINK_FLAGS_WORK )
string ( APPEND MPI_LINK_FLAGS_WORK " ${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}" )
else ( )
set ( MPI_LINK_FLAGS_WORK "${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}" )
endif ( )
endforeach ( )
endif ( )
2023-11-01 06:11:15 +08:00
# Deal with the libraries given with full path next
unset ( MPI_DIRECT_LIB_NAMES_WORK )
foreach ( _MPI_LIB_FULLPATH IN LISTS MPI_LIB_FULLPATHS_WORK )
get_filename_component ( _MPI_PLAIN_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME_WE )
list ( APPEND MPI_DIRECT_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}" )
set ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY "${_MPI_LIB_FULLPATH}" CACHE FILEPATH "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" )
mark_as_advanced ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY )
endforeach ( )
# Directly linked objects should be linked first in case some generic linker flags are needed for them.
if ( MPI_DIRECT_LIB_NAMES_WORK )
set ( MPI_PLAIN_LIB_NAMES_WORK "${MPI_DIRECT_LIB_NAMES_WORK};${MPI_PLAIN_LIB_NAMES_WORK}" )
endif ( )
# MPI might require pthread to work. The above mechanism wouldn't detect it, but we need to
# link it in that case. -lpthread is covered by the normal library treatment on the other hand.
if ( "${MPI_COMPILE_CMDLINE}" MATCHES "-pthread" )
list ( APPEND MPI_COMPILE_OPTIONS_WORK "-pthread" )
if ( MPI_LINK_FLAGS_WORK )
string ( APPEND MPI_LINK_FLAGS_WORK " -pthread" )
else ( )
set ( MPI_LINK_FLAGS_WORK "-pthread" )
endif ( )
endif ( )
if ( MPI_ ${ LANG } _EXTRA_COMPILE_DEFINITIONS )
list ( APPEND MPI_COMPILE_DEFINITIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS}" )
endif ( )
if ( MPI_ ${ LANG } _EXTRA_COMPILE_OPTIONS )
list ( APPEND MPI_COMPILE_OPTIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_OPTIONS}" )
endif ( )
if ( MPI_ ${ LANG } _EXTRA_LIB_NAMES )
list ( APPEND MPI_PLAIN_LIB_NAMES_WORK "${MPI_${LANG}_EXTRA_LIB_NAMES}" )
endif ( )
# If we found MPI, set up all of the appropriate cache entries
if ( NOT MPI_ ${ LANG } _COMPILE_OPTIONS )
set ( MPI_ ${ LANG } _COMPILE_OPTIONS ${ MPI_COMPILE_OPTIONS_WORK } CACHE STRING "MPI ${LANG} compilation options" FORCE )
endif ( )
if ( NOT MPI_ ${ LANG } _COMPILE_DEFINITIONS )
set ( MPI_ ${ LANG } _COMPILE_DEFINITIONS ${ MPI_COMPILE_DEFINITIONS_WORK } CACHE STRING "MPI ${LANG} compilation definitions" FORCE )
endif ( )
2023-11-01 06:34:31 +08:00
if ( NOT MPI_ ${ LANG } _COMPILER_INCLUDE_DIRS )
set ( MPI_ ${ LANG } _COMPILER_INCLUDE_DIRS ${ MPI_INCLUDE_DIRS_WORK } CACHE STRING "MPI ${LANG} compiler wrapper include directories" FORCE )
2023-11-01 06:11:15 +08:00
endif ( )
if ( NOT MPI_ ${ LANG } _LINK_FLAGS )
set ( MPI_ ${ LANG } _LINK_FLAGS ${ MPI_LINK_FLAGS_WORK } CACHE STRING "MPI ${LANG} linker flags" FORCE )
endif ( )
if ( NOT MPI_ ${ LANG } _LIB_NAMES )
set ( MPI_ ${ LANG } _LIB_NAMES ${ MPI_PLAIN_LIB_NAMES_WORK } CACHE STRING "MPI ${LANG} libraries to link against" FORCE )
endif ( )
set ( MPI_ ${ LANG } _WRAPPER_FOUND TRUE PARENT_SCOPE )
endfunction ( )
function ( _MPI_guess_settings LANG )
set ( MPI_GUESS_FOUND FALSE )
# Currently only MSMPI and MPICH2 on Windows are supported, so we can skip this search if we're not targeting that.
if ( WIN32 )
# MSMPI
# The environment variables MSMPI_INC and MSMPILIB32/64 are the only ways of locating the MSMPI_SDK,
# which is installed separately from the runtime. Thus it's possible to have mpiexec but not MPI headers
# or import libraries and vice versa.
if ( NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MSMPI" )
# We first attempt to locate the msmpi.lib. Should be find it, we'll assume that the MPI present is indeed
# Microsoft MPI.
if ( "${CMAKE_SIZEOF_VOID_P}" EQUAL 8 )
set ( MPI_MSMPI_LIB_PATH "$ENV{MSMPI_LIB64}" )
set ( MPI_MSMPI_INC_PATH_EXTRA "$ENV{MSMPI_INC}/x64" )
else ( )
set ( MPI_MSMPI_LIB_PATH "$ENV{MSMPI_LIB32}" )
set ( MPI_MSMPI_INC_PATH_EXTRA "$ENV{MSMPI_INC}/x86" )
endif ( )
find_library ( MPI_msmpi_LIBRARY
N A M E S m s m p i
H I N T S $ { M P I _ M S M P I _ L I B _ P A T H }
D O C " L o c a t i o n o f t h e m s m p i l i b r a r y f o r M i c r o s o f t M P I " )
mark_as_advanced ( MPI_msmpi_LIBRARY )
if ( MPI_msmpi_LIBRARY )
# Next, we attempt to locate the MPI header. Note that for Fortran we know that mpif.h is a way
# MSMPI can be used and therefore that header has to be present.
if ( NOT MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
get_filename_component ( MPI_MSMPI_INC_DIR "$ENV{MSMPI_INC}" REALPATH )
set ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS "${MPI_MSMPI_INC_DIR}" CACHE STRING "MPI ${LANG} additional include directories" FORCE )
unset ( MPI_MSMPI_INC_DIR )
endif ( )
# For MSMPI, one can compile the MPI module by building the mpi.f90 shipped with the MSMPI SDK,
# thus it might be present or provided by the user. Figuring out which is supported is done later on.
# The PGI Fortran compiler for instance ships a prebuilt set of modules in its own include folder.
# Should a user be employing PGI or have built its own set and provided it via cache variables, the
# splitting routine would have located the module files.
# For C and C++, we're done here (MSMPI does not ship the MPI-2 C++ bindings) - however, for Fortran
# we need some extra library to glue Fortran support together:
# MSMPI ships 2-4 Fortran libraries, each for different Fortran compiler behaviors. The library names
# ending with a c are using the cdecl calling convention, whereas those ending with an s are for Fortran
# implementations using stdcall. Therefore, the 64-bit MSMPI only ships those ending in 'c', whereas the 32-bit
# has both variants available.
# The second difference is the last but one letter, if it's an e(nd), the length of a string argument is
# passed by the Fortran compiler after all other arguments on the parameter list, if it's an m(ixed),
# it's passed immediately after the string address.
# To summarize:
# - msmpifec: CHARACTER length passed after the parameter list and using cdecl calling convention
# - msmpifmc: CHARACTER length passed directly after string address and using cdecl calling convention
# - msmpifes: CHARACTER length passed after the parameter list and using stdcall calling convention
# - msmpifms: CHARACTER length passed directly after string address and using stdcall calling convention
# 32-bit MSMPI ships all four libraries, 64-bit MSMPI ships only the first two.
# As is, Intel Fortran and PGI Fortran both use the 'ec' variant of the calling convention, whereas
# the old Compaq Visual Fortran compiler defaulted to the 'ms' version. It's possible to make Intel Fortran
# use the CVF calling convention using /iface:cvf, but we assume - and this is also assumed in FortranCInterface -
# this isn't the case. It's also possible to make CVF use the 'ec' variant, using /iface=(cref,nomixed_str_len_arg).
# Our strategy is now to locate all libraries, but enter msmpifec into the LIB_NAMES array.
# Should this not be adequate it's a straightforward way for a user to change the LIB_NAMES array and
# have his library found. Still, this should not be necessary outside of exceptional cases, as reasoned.
if ( "${LANG}" STREQUAL "Fortran" )
set ( MPI_MSMPI_CALLINGCONVS c )
if ( "${CMAKE_SIZEOF_VOID_P}" EQUAL 4 )
list ( APPEND MPI_MSMPI_CALLINGCONVS s )
endif ( )
foreach ( mpistrlenpos IN ITEMS e m )
foreach ( mpicallingconv IN LISTS MPI_MSMPI_CALLINGCONVS )
find_library ( MPI_msmpif ${ mpistrlenpos } ${ mpicallingconv } _LIBRARY
N A M E S m s m p i f $ { m p i s t r l e n p o s } $ { m p i c a l l i n g c o n v }
H I N T S " $ { M P I _ M S M P I _ L I B _ P A T H } "
D O C " L o c a t i o n o f t h e m s m p i $ { m p i s t r l e n p o s } $ { m p i c a l l i n g c o n v } l i b r a r y f o r M i c r o s o f t M P I " )
mark_as_advanced ( MPI_msmpif ${ mpistrlenpos } ${ mpicallingconv } _LIBRARY )
endforeach ( )
endforeach ( )
if ( NOT MPI_ ${ LANG } _LIB_NAMES )
set ( MPI_ ${ LANG } _LIB_NAMES "msmpi;msmpifec" CACHE STRING "MPI ${LANG} libraries to link against" FORCE )
endif ( )
# At this point we're *not* done. MSMPI requires an additional include file for Fortran giving the value
# of MPI_AINT. This file is called mpifptr.h located in the x64 and x86 subfolders, respectively.
find_path ( MPI_mpifptr_INCLUDE_DIR
N A M E S " m p i f p t r . h "
H I N T S " $ { M P I _ M S M P I _ I N C _ P A T H _ E X T R A } "
D O C " L o c a t i o n o f t h e m p i f p t r . h e x t r a h e a d e r f o r M i c r o s o f t M P I " )
if ( NOT MPI_ ${ LANG } _ADDITIONAL_INCLUDE_VARS )
set ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_VARS "mpifptr" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI_<name>_INCLUDE_DIR." FORCE )
endif ( )
mark_as_advanced ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_VARS MPI_mpifptr_INCLUDE_DIR )
else ( )
if ( NOT MPI_ ${ LANG } _LIB_NAMES )
set ( MPI_ ${ LANG } _LIB_NAMES "msmpi" CACHE STRING "MPI ${LANG} libraries to link against" FORCE )
endif ( )
endif ( )
mark_as_advanced ( MPI_ ${ LANG } _LIB_NAMES )
set ( MPI_GUESS_FOUND TRUE )
if ( _MPIEXEC_NOT_GIVEN )
unset ( MPIEXEC_EXECUTABLE CACHE )
endif ( )
find_program ( MPIEXEC_EXECUTABLE
N A M E S m p i e x e c
H I N T S $ E N V { M S M P I _ B I N } " [ H K E Y _ L O C A L _ M A C H I N E \ \ S O F T W A R E \ \ M i c r o s o f t \ \ M P I ; I n s t a l l R o o t ] / B i n "
D O C " E x e c u t a b l e f o r r u n n i n g M P I p r o g r a m s . " )
endif ( )
endif ( )
# At this point there's not many MPIs that we could still consider.
# OpenMPI 1.6.x and below supported Windows, but these ship compiler wrappers that still work.
# The only other relevant MPI implementation without a wrapper is MPICH2, which had Windows support in 1.4.1p1 and older.
if ( NOT MPI_GUESS_FOUND AND ( NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MPICH2" ) )
set ( MPI_MPICH_PREFIX_PATHS
" $ E N V { P r o g r a m W 6 4 3 2 } / M P I C H 2 / l i b "
" [ H K E Y _ L O C A L _ M A C H I N E \ \ S O F T W A R E \ \ M P I C H \ \ S M P D ; b i n a r y ] / . . / l i b "
" [ H K E Y _ L O C A L _ M A C H I N E \ \ S O F T W A R E \ \ M P I C H 2 ; P a t h ] / l i b "
)
# All of C, C++ and Fortran will need mpi.lib, so we'll look for this first
find_library ( MPI_mpi_LIBRARY
N A M E S m p i
H I N T S $ { M P I _ M P I C H _ P R E F I X _ P A T H S } )
mark_as_advanced ( MPI_mpi_LIBRARY )
# If we found mpi.lib, we detect the rest of MPICH2
if ( MPI_mpi_LIBRARY )
set ( MPI_MPICH_LIB_NAMES "mpi" )
# If MPI-2 C++ bindings are requested, we need to locate cxx.lib as well.
# Otherwise, MPICH_SKIP_MPICXX will be defined and these bindings aren't needed.
if ( "${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX )
find_library ( MPI_cxx_LIBRARY
N A M E S c x x
H I N T S $ { M P I _ M P I C H _ P R E F I X _ P A T H S } )
mark_as_advanced ( MPI_cxx_LIBRARY )
list ( APPEND MPI_MPICH_LIB_NAMES "cxx" )
# For Fortran, MPICH2 provides three different libraries:
# fmpich2.lib which uses uppercase symbols and cdecl,
# fmpich2s.lib which uses uppercase symbols and stdcall (32-bit only),
# fmpich2g.lib which uses lowercase symbols with double underscores and cdecl.
# fmpich2s.lib would be useful for Compaq Visual Fortran, fmpich2g.lib has to be used with GNU g77 and is also
# provided in the form of an .a archive for MinGW and Cygwin. From our perspective, fmpich2.lib is the only one
# we need to try, and if it doesn't work with the given Fortran compiler we'd find out later on during validation
elseif ( "${LANG}" STREQUAL "Fortran" )
find_library ( MPI_fmpich2_LIBRARY
N A M E S f m p i c h 2
H I N T S $ { M P I _ M P I C H _ P R E F I X _ P A T H S } )
find_library ( MPI_fmpich2s_LIBRARY
N A M E S f m p i c h 2 s
H I N T S $ { M P I _ M P I C H _ P R E F I X _ P A T H S } )
find_library ( MPI_fmpich2g_LIBRARY
N A M E S f m p i c h 2 g
H I N T S $ { M P I _ M P I C H _ P R E F I X _ P A T H S } )
mark_as_advanced ( MPI_fmpich2_LIBRARY MPI_fmpich2s_LIBRARY MPI_fmpich2g_LIBRARY )
list ( APPEND MPI_MPICH_LIB_NAMES "fmpich2" )
endif ( )
if ( NOT MPI_ ${ LANG } _LIB_NAMES )
set ( MPI_ ${ LANG } _LIB_NAMES "${MPI_MPICH_LIB_NAMES}" CACHE STRING "MPI ${LANG} libraries to link against" FORCE )
endif ( )
unset ( MPI_MPICH_LIB_NAMES )
if ( NOT MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
# For MPICH2, the include folder would be in ../include relative to the library folder.
get_filename_component ( MPI_MPICH_ROOT_DIR "${MPI_mpi_LIBRARY}" DIRECTORY )
get_filename_component ( MPI_MPICH_ROOT_DIR "${MPI_MPICH_ROOT_DIR}" DIRECTORY )
if ( IS_DIRECTORY "${MPI_MPICH_ROOT_DIR}/include" )
set ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS "${MPI_MPICH_ROOT_DIR}/include" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI_<name>_INCLUDE_DIR." FORCE )
endif ( )
unset ( MPI_MPICH_ROOT_DIR )
endif ( )
set ( MPI_GUESS_FOUND TRUE )
if ( _MPIEXEC_NOT_GIVEN )
unset ( MPIEXEC_EXECUTABLE CACHE )
endif ( )
find_program ( MPIEXEC_EXECUTABLE
N A M E S $ { _ M P I E X E C _ N A M E S }
H I N T S " $ E N V { P r o g r a m W 6 4 3 2 } / M P I C H 2 / b i n "
" [ H K E Y _ L O C A L _ M A C H I N E \ \ S O F T W A R E \ \ M P I C H \ \ S M P D ; b i n a r y ] "
" [ H K E Y _ L O C A L _ M A C H I N E \ \ S O F T W A R E \ \ M P I C H 2 ; P a t h ] / b i n "
D O C " E x e c u t a b l e f o r r u n n i n g M P I p r o g r a m s . " )
endif ( )
unset ( MPI_MPICH_PREFIX_PATHS )
endif ( )
endif ( )
set ( MPI_ ${ LANG } _GUESS_FOUND "${MPI_GUESS_FOUND}" PARENT_SCOPE )
endfunction ( )
function ( _MPI_adjust_compile_definitions LANG )
if ( "${LANG}" STREQUAL "CXX" )
# To disable the C++ bindings, we need to pass some definitions since the mpi.h header has to deal with both C and C++
# bindings in MPI-2.
if ( MPI_CXX_SKIP_MPICXX AND NOT MPI_ ${ LANG } _COMPILE_DEFINITIONS MATCHES "SKIP_MPICXX" )
# MPICH_SKIP_MPICXX is being used in MPICH and derivatives like MVAPICH or Intel MPI
# OMPI_SKIP_MPICXX is being used in Open MPI
# _MPICC_H is being used for IBM Platform MPI
list ( APPEND MPI_ ${ LANG } _COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX" "OMPI_SKIP_MPICXX" "_MPICC_H" )
set ( MPI_ ${ LANG } _COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}" CACHE STRING "MPI ${LANG} compilation definitions" FORCE )
endif ( )
endif ( )
endfunction ( )
macro ( _MPI_assemble_libraries LANG )
set ( MPI_ ${ LANG } _LIBRARIES "" )
# Only for libraries do we need to check whether the compiler's linking stage is separate.
if ( NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_ ${ LANG } _WORKS_IMPLICIT )
foreach ( mpilib IN LISTS MPI_ ${ LANG } _LIB_NAMES )
list ( APPEND MPI_ ${ LANG } _LIBRARIES ${ MPI_${mpilib } _LIBRARY} )
endforeach ( )
endif ( )
endmacro ( )
macro ( _MPI_assemble_include_dirs LANG )
2023-11-01 06:34:31 +08:00
set ( MPI_ ${ LANG } _INCLUDE_DIRS
$ { M P I _ $ { L A N G } _ C O M P I L E R _ I N C L U D E _ D I R S }
$ { M P I _ $ { L A N G } _ A D D I T I O N A L _ I N C L U D E _ D I R S }
)
if ( "${LANG}" MATCHES "(C|CXX)" )
if ( MPI_ ${ LANG } _HEADER_DIR )
list ( APPEND MPI_ ${ LANG } _INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}" )
2023-11-01 06:11:15 +08:00
endif ( )
2023-11-01 06:34:31 +08:00
else ( ) # Fortran
if ( MPI_ ${ LANG } _F77_HEADER_DIR )
list ( APPEND MPI_ ${ LANG } _INCLUDE_DIRS "${MPI_${LANG}_F77_HEADER_DIR}" )
endif ( )
if ( MPI_ ${ LANG } _MODULE_DIR )
list ( APPEND MPI_ ${ LANG } _INCLUDE_DIRS "${MPI_${LANG}_MODULE_DIR}" )
2023-11-01 06:11:15 +08:00
endif ( )
endif ( )
2023-11-01 06:34:31 +08:00
if ( MPI_ ${ LANG } _INCLUDE_DIRS )
list ( REMOVE_DUPLICATES MPI_ ${ LANG } _INCLUDE_DIRS )
endif ( )
2023-11-01 06:11:15 +08:00
endmacro ( )
2023-11-01 06:34:31 +08:00
macro ( _MPI_split_include_dirs LANG )
2023-11-01 06:11:15 +08:00
# Backwards compatibility: Search INCLUDE_PATH if given.
if ( MPI_ ${ LANG } _INCLUDE_PATH )
list ( APPEND MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_INCLUDE_PATH}" )
endif ( )
# We try to find the headers/modules among those paths (and system paths)
# For C/C++, we just need to have a look for mpi.h.
if ( "${LANG}" MATCHES "(C|CXX)" )
find_path ( MPI_ ${ LANG } _HEADER_DIR "mpi.h"
2023-11-01 06:34:31 +08:00
H I N T S
$ { M P I _ $ { L A N G } _ C O M P I L E R _ I N C L U D E _ D I R S }
$ { M P I _ $ { L A N G } _ A D D I T I O N A L _ I N C L U D E _ D I R S }
2023-11-01 06:11:15 +08:00
)
mark_as_advanced ( MPI_ ${ LANG } _HEADER_DIR )
if ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
list ( REMOVE_ITEM MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}" )
endif ( )
2023-11-01 06:34:31 +08:00
2023-11-01 06:11:15 +08:00
# Fortran is more complicated here: An implementation could provide
# any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI
# only provides Fortran 77 and - if mpi.f90 is built - potentially
# a Fortran 90 module.
elseif ( "${LANG}" STREQUAL "Fortran" )
find_path ( MPI_ ${ LANG } _F77_HEADER_DIR "mpif.h"
2023-11-01 06:34:31 +08:00
H I N T S
$ { M P I _ $ { L A N G } _ C O M P I L E R _ I N C L U D E _ D I R S }
$ { M P I _ $ { L A N G } _ A D D I T I O N A L _ I N C L U D E _ D I R S }
2023-11-01 06:11:15 +08:00
)
find_path ( MPI_ ${ LANG } _MODULE_DIR
N A M E S " m p i . m o d " " m p i _ f 0 8 . m o d "
2023-11-01 06:34:31 +08:00
H I N T S
$ { M P I _ $ { L A N G } _ C O M P I L E R _ I N C L U D E _ D I R S }
$ { M P I _ $ { L A N G } _ A D D I T I O N A L _ I N C L U D E _ D I R S }
2023-11-01 06:11:15 +08:00
)
if ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
list ( REMOVE_ITEM MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS
" $ { M P I _ $ { L A N G } _ F 7 7 _ H E A D E R _ D I R } "
" $ { M P I _ $ { L A N G } _ M O D U L E _ D I R } "
)
endif ( )
mark_as_advanced ( MPI_ ${ LANG } _F77_HEADER_DIR MPI_ ${ LANG } _MODULE_DIR )
endif ( )
2023-11-01 06:34:31 +08:00
2023-11-01 06:11:15 +08:00
# Remove duplicates and default system directories from the list.
if ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
list ( REMOVE_DUPLICATES MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS )
foreach ( MPI_IMPLICIT_INC_DIR IN LISTS CMAKE_ ${ LANG } _IMPLICIT_LINK_DIRECTORIES )
list ( REMOVE_ITEM MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS ${ MPI_IMPLICIT_INC_DIR } )
endforeach ( )
endif ( )
2023-11-01 06:34:31 +08:00
2023-11-01 06:11:15 +08:00
set ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS ${ MPI_${LANG } _ADDITIONAL_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} additional include directories" FORCE )
2023-11-01 06:34:31 +08:00
endmacro ( )
2023-11-01 06:11:15 +08:00
macro ( _MPI_create_imported_target LANG )
if ( NOT TARGET MPI::MPI_ ${ LANG } )
add_library ( MPI::MPI_ ${ LANG } INTERFACE IMPORTED )
endif ( )
# When this is consumed for compiling CUDA, use '-Xcompiler' to wrap '-pthread'.
string ( REPLACE "-pthread" "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-Xcompiler >-pthread"
_ M P I _ $ { L A N G } _ C O M P I L E _ O P T I O N S " $ { M P I _ $ { L A N G } _ C O M P I L E _ O P T I O N S } " )
set_property ( TARGET MPI::MPI_ ${ LANG } PROPERTY INTERFACE_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}" )
unset ( _MPI_ ${ LANG } _COMPILE_OPTIONS )
set_property ( TARGET MPI::MPI_ ${ LANG } PROPERTY INTERFACE_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}" )
if ( MPI_ ${ LANG } _LINK_FLAGS )
2023-11-01 06:20:22 +08:00
set_property ( TARGET MPI::MPI_ ${ LANG } PROPERTY INTERFACE_LINK_OPTIONS "SHELL:${MPI_${LANG}_LINK_FLAGS}" )
2023-11-01 06:11:15 +08:00
endif ( )
# If the compiler links MPI implicitly, no libraries will be found as they're contained within
# CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES already.
if ( MPI_ ${ LANG } _LIBRARIES )
2023-11-01 06:20:22 +08:00
set_property ( TARGET MPI::MPI_ ${ LANG } PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_${LANG}_LIBRARIES}" )
2023-11-01 06:11:15 +08:00
endif ( )
# Given the new design of FindMPI, INCLUDE_DIRS will always be located, even under implicit linking.
set_property ( TARGET MPI::MPI_ ${ LANG } PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MPI_${LANG}_INCLUDE_DIRS}" )
endmacro ( )
2023-11-01 06:20:22 +08:00
function ( _MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRESS_ERRORS )
2023-11-01 06:11:15 +08:00
set ( WORK_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI" )
set ( SRC_DIR "${CMAKE_ROOT}/Modules/FindMPI" )
set ( BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI/${MPI_TEST_FILE_NAME}_${LANG}.bin" )
unset ( MPI_TEST_COMPILE_DEFINITIONS )
if ( "${LANG}" STREQUAL "Fortran" )
if ( "${MODE}" STREQUAL "F90_MODULE" )
set ( MPI_Fortran_INCLUDE_LINE "use mpi\n implicit none" )
elseif ( "${MODE}" STREQUAL "F08_MODULE" )
set ( MPI_Fortran_INCLUDE_LINE "use mpi_f08\n implicit none" )
else ( ) # F77 header
set ( MPI_Fortran_INCLUDE_LINE "implicit none\n include 'mpif.h'" )
endif ( )
configure_file ( "${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" @ONLY )
set ( MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" )
elseif ( "${LANG}" STREQUAL "CXX" )
configure_file ( "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" COPYONLY )
set ( MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" )
if ( "${MODE}" STREQUAL "TEST_MPICXX" )
set ( MPI_TEST_COMPILE_DEFINITIONS TEST_MPI_MPICXX )
endif ( )
else ( ) # C
set ( MPI_TEST_SOURCE_FILE "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" )
endif ( )
if ( RUN_BINARY )
try_run ( MPI_RUN_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE } MPI_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE }
" $ { C M A K E _ B I N A R Y _ D I R } " S O U R C E S " $ { M P I _ T E S T _ S O U R C E _ F I L E } "
C O M P I L E _ D E F I N I T I O N S $ { M P I _ T E S T _ C O M P I L E _ D E F I N I T I O N S }
L I N K _ L I B R A R I E S M P I : : M P I _ $ { L A N G }
2023-11-01 06:20:22 +08:00
R U N _ O U T P U T _ V A R I A B L E M P I _ R U N _ O U T P U T _ $ { L A N G } _ $ { M P I _ T E S T _ F I L E _ N A M E } _ $ { M O D E }
C O M P I L E _ O U T P U T _ V A R I A B L E _ M P I _ T R Y _ $ { M P I _ T E S T _ F I L E _ N A M E } _ $ { M O D E } _ O U T P U T )
2023-11-01 06:11:15 +08:00
set ( MPI_RUN_OUTPUT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE } "${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}" PARENT_SCOPE )
else ( )
try_compile ( MPI_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE }
" $ { C M A K E _ B I N A R Y _ D I R } " S O U R C E S " $ { M P I _ T E S T _ S O U R C E _ F I L E } "
C O M P I L E _ D E F I N I T I O N S $ { M P I _ T E S T _ C O M P I L E _ D E F I N I T I O N S }
L I N K _ L I B R A R I E S M P I : : M P I _ $ { L A N G }
2023-11-01 06:20:22 +08:00
C O P Y _ F I L E " $ { B I N _ F I L E } "
O U T P U T _ V A R I A B L E _ M P I _ T R Y _ $ { M P I _ T E S T _ F I L E _ N A M E } _ $ { M O D E } _ O U T P U T )
endif ( )
if ( NOT SUPPRESS_ERRORS )
if ( NOT MPI_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE } )
file ( APPEND ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeError.log
" T h e M P I t e s t $ { M P I _ T E S T _ F I L E _ N A M E } f o r $ { L A N G } i n m o d e $ { M O D E } f a i l e d t o c o m p i l e w i t h t h e f o l l o w i n g o u t p u t : \ n $ { _ M P I _ T R Y _ $ { M P I _ T E S T _ F I L E _ N A M E } _ $ { M O D E } _ O U T P U T } \ n \ n " )
elseif ( DEFINED MPI_RUN_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE } AND MPI_RUN_RESULT_ ${ LANG } _ ${ MPI_TEST_FILE_NAME } _ ${ MODE } )
file ( APPEND ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /CMakeError.log
" T h e M P I t e s t $ { M P I _ T E S T _ F I L E _ N A M E } f o r $ { L A N G } i n m o d e $ { M O D E } f a i l e d t o r u n w i t h t h e f o l l o w i n g o u t p u t : \ n $ { M P I _ R U N _ O U T P U T _ $ { L A N G } _ $ { M P I _ T E S T _ F I L E _ N A M E } _ $ { M O D E } } \ n \ n " )
endif ( )
2023-11-01 06:11:15 +08:00
endif ( )
endfunction ( )
2023-11-01 06:20:22 +08:00
macro ( _MPI_check_lang_works LANG SUPPRESS_ERRORS )
2023-11-01 06:11:15 +08:00
# For Fortran we may have by the MPI-3 standard an implementation that provides:
# - the mpi_f08 module
# - *both*, the mpi module and 'mpif.h'
# Since older MPI standards (MPI-1) did not define anything but 'mpif.h', we need to check all three individually.
if ( NOT MPI_ ${ LANG } _WORKS )
if ( "${LANG}" STREQUAL "Fortran" )
set ( MPI_Fortran_INTEGER_LINE "(kind=MPI_INTEGER_KIND)" )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } test_mpi F77_HEADER FALSE ${ SUPPRESS_ERRORS } )
_MPI_try_staged_settings ( ${ LANG } test_mpi F90_MODULE FALSE ${ SUPPRESS_ERRORS } )
_MPI_try_staged_settings ( ${ LANG } test_mpi F08_MODULE FALSE ${ SUPPRESS_ERRORS } )
2023-11-01 06:11:15 +08:00
set ( MPI_ ${ LANG } _WORKS FALSE )
foreach ( mpimethod IN ITEMS F77_HEADER F08_MODULE F90_MODULE )
if ( MPI_RESULT_ ${ LANG } _test_mpi_ ${ mpimethod } )
set ( MPI_ ${ LANG } _WORKS TRUE )
set ( MPI_ ${ LANG } _HAVE_ ${ mpimethod } TRUE )
else ( )
set ( MPI_ ${ LANG } _HAVE_ ${ mpimethod } FALSE )
endif ( )
endforeach ( )
# MPI-1 versions had no MPI_INTGER_KIND defined, so we need to try without it.
# However, MPI-1 also did not define the Fortran 90 and 08 modules, so we only try the F77 header.
unset ( MPI_Fortran_INTEGER_LINE )
if ( NOT MPI_ ${ LANG } _WORKS )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } test_mpi F77_HEADER_NOKIND FALSE ${ SUPPRESS_ERRORS } )
2023-11-01 06:11:15 +08:00
if ( MPI_RESULT_ ${ LANG } _test_mpi_F77_HEADER_NOKIND )
set ( MPI_ ${ LANG } _WORKS TRUE )
set ( MPI_ ${ LANG } _HAVE_F77_HEADER TRUE )
endif ( )
endif ( )
else ( )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } test_mpi normal FALSE ${ SUPPRESS_ERRORS } )
2023-11-01 06:11:15 +08:00
# If 'test_mpi' built correctly, we've found valid MPI settings. There might not be MPI-2 C++ support, but there can't
# be MPI-2 C++ support without the C bindings being present, so checking for them is sufficient.
set ( MPI_ ${ LANG } _WORKS "${MPI_RESULT_${LANG}_test_mpi_normal}" )
endif ( )
endif ( )
endmacro ( )
# Some systems install various MPI implementations in separate folders in some MPI prefix
# This macro enumerates all such subfolders and adds them to the list of hints that will be searched.
macro ( MPI_search_mpi_prefix_folder PREFIX_FOLDER )
if ( EXISTS "${PREFIX_FOLDER}" )
file ( GLOB _MPI_folder_children RELATIVE "${PREFIX_FOLDER}" "${PREFIX_FOLDER}/*" )
foreach ( _MPI_folder_child IN LISTS _MPI_folder_children )
if ( IS_DIRECTORY "${PREFIX_FOLDER}/${_MPI_folder_child}" )
list ( APPEND MPI_HINT_DIRS "${PREFIX_FOLDER}/${_MPI_folder_child}" )
endif ( )
endforeach ( )
endif ( )
endmacro ( )
set ( MPI_HINT_DIRS ${ MPI_HOME } $ENV{ MPI_HOME } $ENV{ I_MPI_ROOT } )
if ( "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux" )
# SUSE Linux Enterprise Server stores its MPI implementations under /usr/lib64/mpi/gcc/<name>
# We enumerate the subfolders and append each as a prefix
MPI_search_mpi_prefix_folder ( "/usr/lib64/mpi/gcc" )
elseif ( "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "FreeBSD" )
# FreeBSD ships mpich under the normal system paths - but available openmpi implementations
# will be found in /usr/local/mpi/<name>
MPI_search_mpi_prefix_folder ( "/usr/local/mpi" )
endif ( )
# Most MPI distributions have some form of mpiexec or mpirun which gives us something we can look for.
# The MPI standard does not mandate the existence of either, but instead only makes requirements if a distribution
# ships an mpiexec program (mpirun executables are not regulated by the standard).
# We defer searching for mpiexec binaries belonging to guesses until later. By doing so, mismatches between mpiexec
# and the MPI we found should be reduced.
if ( NOT MPIEXEC_EXECUTABLE )
set ( _MPIEXEC_NOT_GIVEN TRUE )
else ( )
set ( _MPIEXEC_NOT_GIVEN FALSE )
endif ( )
find_program ( MPIEXEC_EXECUTABLE
N A M E S $ { _ M P I E X E C _ N A M E S }
P A T H _ S U F F I X E S b i n s b i n
H I N T S $ { M P I _ H I N T _ D I R S }
D O C " E x e c u t a b l e f o r r u n n i n g M P I p r o g r a m s . " )
# call get_filename_component twice to remove mpiexec and the directory it exists in (typically bin).
# This gives us a fairly reliable base directory to search for /bin /lib and /include from.
get_filename_component ( _MPI_BASE_DIR "${MPIEXEC_EXECUTABLE}" PATH )
get_filename_component ( _MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH )
# According to the MPI standard, section 8.8 -n is a guaranteed, and the only guaranteed way to
# launch an MPI process using mpiexec if such a program exists.
set ( MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "Flag used by MPI to specify the number of processes for mpiexec; the next option will be the number of processes." )
set ( MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by mpiexec." )
set ( MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will be placed after all flags passed to mpiexec." )
# Set the number of processes to the physical processor count
cmake_host_system_information ( RESULT _MPIEXEC_NUMPROCS QUERY NUMBER_OF_PHYSICAL_CORES )
set ( MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}" CACHE STRING "Maximum number of processors available to run MPI applications." )
unset ( _MPIEXEC_NUMPROCS )
mark_as_advanced ( MPIEXEC_EXECUTABLE MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS )
#=============================================================================
# Backward compatibility input hacks. Propagate the FindMPI hints to C and
# CXX if the respective new versions are not defined. Translate the old
# MPI_LIBRARY and MPI_EXTRA_LIBRARY to respective MPI_${LANG}_LIBRARIES.
#
# Once we find the new variables, we translate them back into their old
# equivalents below.
if ( NOT MPI_IGNORE_LEGACY_VARIABLES )
foreach ( LANG IN ITEMS C CXX )
# Old input variables.
set ( _MPI_OLD_INPUT_VARS COMPILER COMPILE_FLAGS INCLUDE_PATH LINK_FLAGS )
# Set new vars based on their old equivalents, if the new versions are not already set.
foreach ( var ${ _MPI_OLD_INPUT_VARS } )
if ( NOT MPI_ ${ LANG } _ ${ var } AND MPI_ ${ var } )
set ( MPI_ ${ LANG } _ ${ var } "${MPI_${var}}" )
endif ( )
endforeach ( )
# Chop the old compile flags into options and definitions
unset ( MPI_ ${ LANG } _EXTRA_COMPILE_DEFINITIONS )
unset ( MPI_ ${ LANG } _EXTRA_COMPILE_OPTIONS )
if ( MPI_ ${ LANG } _COMPILE_FLAGS )
separate_arguments ( MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}" )
foreach ( _MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS )
if ( "${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)" )
list ( APPEND MPI_ ${ LANG } _EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}" )
else ( )
list ( APPEND MPI_ ${ LANG } _EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}" )
endif ( )
endforeach ( )
unset ( MPI_SEPARATE_FLAGS )
endif ( )
# If a list of libraries was given, we'll split it into new-style cache variables
unset ( MPI_ ${ LANG } _EXTRA_LIB_NAMES )
if ( NOT MPI_ ${ LANG } _LIB_NAMES )
foreach ( _MPI_LIB IN LISTS MPI_ ${ LANG } _LIBRARIES MPI_LIBRARY MPI_EXTRA_LIBRARY )
if ( _MPI_LIB )
get_filename_component ( _MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE )
get_filename_component ( _MPI_LIB_NAME "${_MPI_LIB}" NAME )
get_filename_component ( _MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY )
list ( APPEND MPI_ ${ LANG } _EXTRA_LIB_NAMES "${_MPI_PLAIN_LIB_NAME}" )
find_library ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY
N A M E S " $ { _ M P I _ L I B _ N A M E } " " l i b $ { _ M P I _ L I B _ N A M E } "
H I N T S $ { _ M P I _ L I B _ D I R } $ E N V { M P I _ L I B }
D O C " L o c a t i o n o f t h e $ { _ M P I _ P L A I N _ L I B _ N A M E } l i b r a r y f o r M P I "
)
mark_as_advanced ( MPI_ ${ _MPI_PLAIN_LIB_NAME } _LIBRARY )
endif ( )
endforeach ( )
endif ( )
endforeach ( )
endif ( )
#=============================================================================
unset ( MPI_VERSION )
unset ( MPI_VERSION_MAJOR )
unset ( MPI_VERSION_MINOR )
unset ( _MPI_MIN_VERSION )
# If the user specified a library name we assume they prefer that library over a wrapper. If not, they can disable skipping manually.
if ( NOT DEFINED MPI_SKIP_COMPILER_WRAPPER AND MPI_GUESS_LIBRARY_NAME )
set ( MPI_SKIP_COMPILER_WRAPPER TRUE )
endif ( )
# This loop finds the compilers and sends them off for interrogation.
foreach ( LANG IN ITEMS C CXX Fortran )
if ( CMAKE_ ${ LANG } _COMPILER_LOADED )
if ( NOT MPI_FIND_COMPONENTS )
set ( _MPI_FIND_ ${ LANG } TRUE )
elseif ( ${ LANG } IN_LIST MPI_FIND_COMPONENTS )
set ( _MPI_FIND_ ${ LANG } TRUE )
elseif ( ${ LANG } STREQUAL CXX AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS )
set ( _MPI_FIND_ ${ LANG } TRUE )
else ( )
set ( _MPI_FIND_ ${ LANG } FALSE )
endif ( )
else ( )
set ( _MPI_FIND_ ${ LANG } FALSE )
2023-11-01 06:34:31 +08:00
string ( APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. " )
2023-11-01 06:11:15 +08:00
endif ( )
if ( _MPI_FIND_ ${ LANG } )
if ( ${ LANG } STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS )
set ( MPI_CXX_SKIP_MPICXX FALSE CACHE BOOL "If true, the MPI-2 C++ bindings are disabled using definitions." )
mark_as_advanced ( MPI_CXX_SKIP_MPICXX )
endif ( )
2023-11-01 06:34:31 +08:00
if ( NOT ( MPI_ ${ LANG } _LIB_NAMES AND ( MPI_ ${ LANG } _INCLUDE_PATH OR MPI_ ${ LANG } _INCLUDE_DIRS OR MPI_ ${ LANG } _COMPILER_INCLUDE_DIRS ) ) )
2023-11-01 06:11:15 +08:00
set ( MPI_ ${ LANG } _TRIED_IMPLICIT FALSE )
set ( MPI_ ${ LANG } _WORKS_IMPLICIT FALSE )
if ( NOT MPI_ ${ LANG } _COMPILER AND NOT MPI_ASSUME_NO_BUILTIN_MPI )
# Should the imported targets be empty, we effectively try whether the compiler supports MPI on its own, which is the case on e.g.
# Cray PrgEnv.
_MPI_create_imported_target ( ${ LANG } )
2023-11-01 06:20:22 +08:00
_MPI_check_lang_works ( ${ LANG } TRUE )
2023-11-01 06:11:15 +08:00
# If the compiler can build MPI code on its own, it functions as an MPI compiler and we'll set the variable to point to it.
if ( MPI_ ${ LANG } _WORKS )
set ( MPI_ ${ LANG } _COMPILER "${CMAKE_${LANG}_COMPILER}" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE )
set ( MPI_ ${ LANG } _WORKS_IMPLICIT TRUE )
endif ( )
set ( MPI_ ${ LANG } _TRIED_IMPLICIT TRUE )
endif ( )
if ( NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_ ${ LANG } _WORKS )
set ( MPI_ ${ LANG } _WRAPPER_FOUND FALSE )
set ( MPI_PINNED_COMPILER FALSE )
if ( NOT MPI_SKIP_COMPILER_WRAPPER )
if ( MPI_ ${ LANG } _COMPILER )
# If the user supplies a compiler *name* instead of an absolute path, assume that we need to find THAT compiler.
if ( NOT IS_ABSOLUTE "${MPI_${LANG}_COMPILER}" )
# Get rid of our default list of names and just search for the name the user wants.
set ( _MPI_ ${ LANG } _COMPILER_NAMES "${MPI_${LANG}_COMPILER}" )
unset ( MPI_ ${ LANG } _COMPILER CACHE )
endif ( )
# If the user specifies a compiler, we don't want to try to search libraries either.
set ( MPI_PINNED_COMPILER TRUE )
endif ( )
# If we have an MPI base directory, we'll try all compiler names in that one first.
# This should prevent mixing different MPI environments
if ( _MPI_BASE_DIR )
find_program ( MPI_ ${ LANG } _COMPILER
N A M E S $ { _ M P I _ $ { L A N G } _ C O M P I L E R _ N A M E S }
P A T H _ S U F F I X E S b i n s b i n
H I N T S $ { _ M P I _ B A S E _ D I R }
N O _ D E F A U L T _ P A T H
D O C " M P I c o m p i l e r f o r $ { L A N G } "
)
endif ( )
# If the base directory did not help (for example because the mpiexec isn't in the same directory as the compilers),
# we shall try searching in the default paths.
find_program ( MPI_ ${ LANG } _COMPILER
N A M E S $ { _ M P I _ $ { L A N G } _ C O M P I L E R _ N A M E S }
P A T H _ S U F F I X E S b i n s b i n
D O C " M P I c o m p i l e r f o r $ { L A N G } "
)
if ( "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" )
set ( MPI_PINNED_COMPILER TRUE )
# If we haven't made the implicit compiler test yet, perform it now.
if ( NOT MPI_ ${ LANG } _TRIED_IMPLICIT )
_MPI_create_imported_target ( ${ LANG } )
2023-11-01 06:20:22 +08:00
_MPI_check_lang_works ( ${ LANG } TRUE )
2023-11-01 06:11:15 +08:00
endif ( )
# Should the MPI compiler not work implicitly for MPI, still interrogate it.
# Otherwise, MPI compilers for which CMake has separate linking stages, e.g. Intel MPI on Windows where link.exe is being used
# directly during linkage instead of CMAKE_<LANG>_COMPILER will not work.
if ( NOT MPI_ ${ LANG } _WORKS )
set ( MPI_ ${ LANG } _WORKS_IMPLICIT FALSE )
_MPI_interrogate_compiler ( ${ LANG } )
else ( )
set ( MPI_ ${ LANG } _WORKS_IMPLICIT TRUE )
endif ( )
elseif ( MPI_ ${ LANG } _COMPILER )
_MPI_interrogate_compiler ( ${ LANG } )
endif ( )
endif ( )
if ( NOT MPI_PINNED_COMPILER AND NOT MPI_ ${ LANG } _WRAPPER_FOUND )
# If MPI_PINNED_COMPILER wasn't given, and the MPI compiler we potentially found didn't work, we withdraw it.
set ( MPI_ ${ LANG } _COMPILER "MPI_${LANG}_COMPILER-NOTFOUND" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE )
if ( NOT MPI_SKIP_GUESSING )
# For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the
# settings for C. An MPI distribution that is in this situation would be IBM Platform MPI.
if ( "${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND )
set ( MPI_ ${ LANG } _COMPILE_OPTIONS ${ MPI_C_COMPILE_OPTIONS } CACHE STRING "MPI ${LANG} compilation options" )
set ( MPI_ ${ LANG } _COMPILE_DEFINITIONS ${ MPI_C_COMPILE_DEFINITIONS } CACHE STRING "MPI ${LANG} compilation definitions" )
2023-11-01 06:34:31 +08:00
set ( MPI_ ${ LANG } _COMPILER_INCLUDE_DIRS ${ MPI_C_INCLUDE_DIRS } CACHE STRING "MPI ${LANG} compiler wrapper include directories" )
2023-11-01 06:11:15 +08:00
set ( MPI_ ${ LANG } _LINK_FLAGS ${ MPI_C_LINK_FLAGS } CACHE STRING "MPI ${LANG} linker flags" )
set ( MPI_ ${ LANG } _LIB_NAMES ${ MPI_C_LIB_NAMES } CACHE STRING "MPI ${LANG} libraries to link against" )
else ( )
_MPI_guess_settings ( ${ LANG } )
endif ( )
endif ( )
endif ( )
endif ( )
endif ( )
2023-11-01 06:34:31 +08:00
if ( NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" )
_MPI_split_include_dirs ( ${ LANG } )
_MPI_assemble_include_dirs ( ${ LANG } )
else ( )
set ( MPI_ ${ LANG } _INCLUDE_DIRS "" )
endif ( )
2023-11-01 06:11:15 +08:00
_MPI_assemble_libraries ( ${ LANG } )
_MPI_adjust_compile_definitions ( ${ LANG } )
# We always create imported targets even if they're empty
_MPI_create_imported_target ( ${ LANG } )
if ( NOT MPI_ ${ LANG } _WORKS )
2023-11-01 06:20:22 +08:00
_MPI_check_lang_works ( ${ LANG } FALSE )
2023-11-01 06:11:15 +08:00
endif ( )
# Next, we'll initialize the MPI variables that have not been previously set.
set ( MPI_ ${ LANG } _COMPILE_OPTIONS "" CACHE STRING "MPI ${LANG} compilation flags" )
set ( MPI_ ${ LANG } _COMPILE_DEFINITIONS "" CACHE STRING "MPI ${LANG} compilation definitions" )
2023-11-01 06:34:31 +08:00
set ( MPI_ ${ LANG } _COMPILER_INCLUDE_DIRS "" CACHE STRING "MPI ${LANG} compiler wrapper include directories" )
2023-11-01 06:11:15 +08:00
set ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "MPI ${LANG} additional include directories" )
set ( MPI_ ${ LANG } _LINK_FLAGS "" CACHE STRING "MPI ${LANG} linker flags" )
if ( NOT MPI_ ${ LANG } _COMPILER STREQUAL CMAKE_ ${ LANG } _COMPILER )
set ( MPI_ ${ LANG } _LIB_NAMES "" CACHE STRING "MPI ${LANG} libraries to link against" )
endif ( )
2023-11-01 06:34:31 +08:00
mark_as_advanced (
M P I _ $ { L A N G } _ C O M P I L E _ O P T I O N S
M P I _ $ { L A N G } _ C O M P I L E _ D E F I N I T I O N S
M P I _ $ { L A N G } _ L I N K _ F L A G S
M P I _ $ { L A N G } _ L I B _ N A M E S
M P I _ $ { L A N G } _ C O M P I L E R _ I N C L U D E _ D I R S
M P I _ $ { L A N G } _ A D D I T I O N A L _ I N C L U D E _ D I R S
M P I _ $ { L A N G } _ C O M P I L E R
)
2023-11-01 06:11:15 +08:00
# If we've found MPI, then we'll perform additional analysis: Determine the MPI version, MPI library version, supported
# MPI APIs (i.e. MPI-2 C++ bindings). For Fortran we also need to find specific parameters if we're under MPI-3.
if ( MPI_ ${ LANG } _WORKS )
if ( "${LANG}" STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND )
if ( NOT MPI_CXX_SKIP_MPICXX AND NOT MPI_CXX_VALIDATE_SKIP_MPICXX )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } test_mpi MPICXX FALSE FALSE )
2023-11-01 06:11:15 +08:00
if ( MPI_RESULT_ ${ LANG } _test_mpi_MPICXX )
set ( MPI_MPICXX_FOUND TRUE )
else ( )
set ( MPI_MPICXX_FOUND FALSE )
endif ( )
else ( )
set ( MPI_MPICXX_FOUND FALSE )
endif ( )
endif ( )
# At this point, we know the bindings present but not the MPI version or anything else.
if ( NOT DEFINED MPI_ ${ LANG } _VERSION )
unset ( MPI_ ${ LANG } _VERSION_MAJOR )
unset ( MPI_ ${ LANG } _VERSION_MINOR )
endif ( )
set ( MPI_BIN_FOLDER ${ CMAKE_BINARY_DIR } ${ CMAKE_FILES_DIRECTORY } /FindMPI )
# For Fortran, we'll want to use the most modern MPI binding to test capabilities other than the
# Fortran parameters, since those depend on the method of consumption.
# For C++, we can always use the C bindings, and should do so, since the C++ bindings do not exist in MPI-3
# whereas the C bindings do, and the C++ bindings never offered any feature advantage over their C counterparts.
if ( "${LANG}" STREQUAL "Fortran" )
if ( MPI_ ${ LANG } _HAVE_F08_MODULE )
set ( MPI_ ${ LANG } _HIGHEST_METHOD F08_MODULE )
elseif ( MPI_ ${ LANG } _HAVE_F90_MODULE )
set ( MPI_ ${ LANG } _HIGHEST_METHOD F90_MODULE )
else ( )
set ( MPI_ ${ LANG } _HIGHEST_METHOD F77_HEADER )
endif ( )
# Another difference between C and Fortran is that we can't use the preprocessor to determine whether MPI_VERSION
# and MPI_SUBVERSION are provided. These defines did not exist in MPI 1.0 and 1.1 and therefore might not
# exist. For C/C++, test_mpi.c will handle the MPI_VERSION extraction, but for Fortran, we need mpiver.f90.
if ( NOT DEFINED MPI_ ${ LANG } _VERSION )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } mpiver ${ MPI_${LANG } _HIGHEST_METHOD} FALSE FALSE )
2023-11-01 06:11:15 +08:00
if ( MPI_RESULT_ ${ LANG } _mpiver_ ${ MPI_${LANG } _HIGHEST_METHOD} )
file ( STRINGS ${ MPI_BIN_FOLDER } /mpiver_ ${ LANG } .bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER" )
if ( "${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*" )
set ( MPI_ ${ LANG } _VERSION_MAJOR "${CMAKE_MATCH_1}" )
set ( MPI_ ${ LANG } _VERSION_MINOR "${CMAKE_MATCH_2}" )
set ( MPI_ ${ LANG } _VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}" )
endif ( )
endif ( )
endif ( )
# Finally, we want to find out which capabilities a given interface supports, compare the MPI-3 standard.
# This is determined by interface specific parameters MPI_SUBARRAYS_SUPPORTED and MPI_ASYNC_PROTECTS_NONBLOCKING
# and might vary between the different methods of consumption.
if ( MPI_DETERMINE_Fortran_CAPABILITIES AND NOT MPI_Fortran_CAPABILITIES_DETERMINED )
foreach ( mpimethod IN ITEMS F08_MODULE F90_MODULE F77_HEADER )
if ( MPI_ ${ LANG } _HAVE_ ${ mpimethod } )
set ( MPI_ ${ LANG } _ ${ mpimethod } _SUBARRAYS FALSE )
set ( MPI_ ${ LANG } _ ${ mpimethod } _ASYNCPROT FALSE )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } fortranparam_mpi ${ mpimethod } TRUE FALSE )
2023-11-01 06:11:15 +08:00
if ( MPI_RESULT_ ${ LANG } _fortranparam_mpi_ ${ mpimethod } AND
N O T " $ { M P I _ R U N _ R E S U L T _ $ { L A N G } _ f o r t r a n p a r a m _ m p i _ $ { m p i m e t h o d } } " S T R E Q U A L " F A I L E D _ T O _ R U N " )
if ( "${MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod}}" MATCHES
" . * I N F O : S U B A R R A Y S \ \ [ * ( [ T F ] ) * \ \ ] - A S Y N C P R O T \ \ [ * ( [ T F ] ) * \ \ ] . * " )
if ( "${CMAKE_MATCH_1}" STREQUAL "T" )
set ( MPI_ ${ LANG } _ ${ mpimethod } _SUBARRAYS TRUE )
endif ( )
if ( "${CMAKE_MATCH_2}" STREQUAL "T" )
set ( MPI_ ${ LANG } _ ${ mpimethod } _ASYNCPROT TRUE )
endif ( )
endif ( )
endif ( )
endif ( )
endforeach ( )
set ( MPI_Fortran_CAPABILITIES_DETERMINED TRUE )
endif ( )
else ( )
set ( MPI_ ${ LANG } _HIGHEST_METHOD normal )
# By the MPI-2 standard, MPI_VERSION and MPI_SUBVERSION are valid for both C and C++ bindings.
if ( NOT DEFINED MPI_ ${ LANG } _VERSION )
file ( STRINGS ${ MPI_BIN_FOLDER } /test_mpi_ ${ LANG } .bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER" )
if ( "${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*" )
set ( MPI_ ${ LANG } _VERSION_MAJOR "${CMAKE_MATCH_1}" )
set ( MPI_ ${ LANG } _VERSION_MINOR "${CMAKE_MATCH_2}" )
set ( MPI_ ${ LANG } _VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}" )
endif ( )
endif ( )
endif ( )
unset ( MPI_BIN_FOLDER )
# At this point, we have dealt with determining the MPI version and parameters for each Fortran method available.
# The one remaining issue is to determine which MPI library is installed.
# Determining the version and vendor of the MPI library is only possible via MPI_Get_library_version() at runtime,
# and therefore we cannot do this while cross-compiling (a user may still define MPI_<lang>_LIBRARY_VERSION_STRING
# themselves and we'll attempt splitting it, which is equivalent to provide the try_run output).
# It's also worth noting that the installed version string can depend on the language, or on the system the binary
# runs on if MPI is not statically linked.
if ( MPI_DETERMINE_LIBRARY_VERSION AND NOT MPI_ ${ LANG } _LIBRARY_VERSION_STRING )
2023-11-01 06:20:22 +08:00
_MPI_try_staged_settings ( ${ LANG } libver_mpi ${ MPI_${LANG } _HIGHEST_METHOD} TRUE FALSE )
2023-11-01 06:11:15 +08:00
if ( MPI_RESULT_ ${ LANG } _libver_mpi_ ${ MPI_${LANG } _HIGHEST_METHOD} AND
" $ { M P I _ R U N _ R E S U L T _ $ { L A N G } _ l i b v e r _ m p i _ $ { M P I _ $ { L A N G } _ H I G H E S T _ M E T H O D } } " E Q U A L " 0 " )
string ( STRIP "${MPI_RUN_OUTPUT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}"
M P I _ $ { L A N G } _ L I B R A R Y _ V E R S I O N _ S T R I N G )
else ( )
set ( MPI_ ${ LANG } _LIBRARY_VERSION_STRING "NOTFOUND" )
endif ( )
endif ( )
endif ( )
set ( MPI_ ${ LANG } _FIND_QUIETLY ${ MPI_FIND_QUIETLY } )
set ( MPI_ ${ LANG } _FIND_VERSION ${ MPI_FIND_VERSION } )
set ( MPI_ ${ LANG } _FIND_VERSION_EXACT ${ MPI_FIND_VERSION_EXACT } )
unset ( MPI_ ${ LANG } _REQUIRED_VARS )
if ( NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" )
foreach ( mpilibname IN LISTS MPI_ ${ LANG } _LIB_NAMES )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${mpilibname}_LIBRARY" )
endforeach ( )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_LIB_NAMES" )
if ( "${LANG}" STREQUAL "Fortran" )
# For Fortran we only need one of the module or header directories to have *some* support for MPI.
if ( NOT MPI_ ${ LANG } _MODULE_DIR )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_F77_HEADER_DIR" )
endif ( )
if ( NOT MPI_ ${ LANG } _F77_HEADER_DIR )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_MODULE_DIR" )
endif ( )
else ( )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_HEADER_DIR" )
endif ( )
if ( MPI_ ${ LANG } _ADDITIONAL_INCLUDE_VARS )
foreach ( mpiincvar IN LISTS MPI_ ${ LANG } _ADDITIONAL_INCLUDE_VARS )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${mpiincvar}_INCLUDE_DIR" )
endforeach ( )
endif ( )
# Append the works variable now. If the settings did not work, this will show up properly.
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_WORKS" )
else ( )
# If the compiler worked implicitly, use its path as output.
# Should the compiler variable be set, we also require it to work.
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_COMPILER" )
if ( MPI_ ${ LANG } _COMPILER )
list ( APPEND MPI_ ${ LANG } _REQUIRED_VARS "MPI_${LANG}_WORKS" )
endif ( )
endif ( )
2023-11-01 06:34:31 +08:00
find_package_handle_standard_args ( MPI_ ${ LANG } NAME_MISMATCHED
R E Q U I R E D _ V A R S $ { M P I _ $ { L A N G } _ R E Q U I R E D _ V A R S }
2023-11-01 06:11:15 +08:00
V E R S I O N _ V A R M P I _ $ { L A N G } _ V E R S I O N )
if ( DEFINED MPI_ ${ LANG } _VERSION )
if ( NOT _MPI_MIN_VERSION OR _MPI_MIN_VERSION VERSION_GREATER MPI_ ${ LANG } _VERSION )
set ( _MPI_MIN_VERSION MPI_ ${ LANG } _VERSION )
endif ( )
endif ( )
endif ( )
endforeach ( )
unset ( _MPI_REQ_VARS )
foreach ( LANG IN ITEMS C CXX Fortran )
if ( ( NOT MPI_FIND_COMPONENTS AND CMAKE_ ${ LANG } _COMPILER_LOADED ) OR LANG IN_LIST MPI_FIND_COMPONENTS )
list ( APPEND _MPI_REQ_VARS "MPI_${LANG}_FOUND" )
endif ( )
endforeach ( )
if ( MPICXX IN_LIST MPI_FIND_COMPONENTS )
list ( APPEND _MPI_REQ_VARS "MPI_MPICXX_FOUND" )
endif ( )
find_package_handle_standard_args ( MPI
R E Q U I R E D _ V A R S $ { _ M P I _ R E Q _ V A R S }
V E R S I O N _ V A R $ { _ M P I _ M I N _ V E R S I O N }
2023-11-01 06:34:31 +08:00
R E A S O N _ F A I L U R E _ M E S S A G E " $ { _ M P I _ F A I L _ R E A S O N } "
2023-11-01 06:11:15 +08:00
H A N D L E _ C O M P O N E N T S )
#=============================================================================
# More backward compatibility stuff
# For compatibility reasons, we also define MPIEXEC
set ( MPIEXEC "${MPIEXEC_EXECUTABLE}" )
# Copy over MPI_<LANG>_INCLUDE_PATH from the assembled INCLUDE_DIRS.
foreach ( LANG IN ITEMS C CXX Fortran )
if ( MPI_ ${ LANG } _FOUND )
set ( MPI_ ${ LANG } _INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}" )
unset ( MPI_ ${ LANG } _COMPILE_FLAGS )
if ( MPI_ ${ LANG } _COMPILE_OPTIONS )
2023-11-01 06:20:22 +08:00
list ( JOIN MPI_ ${ LANG } _COMPILE_OPTIONS " " MPI_ ${ LANG } _COMPILE_FLAGS )
2023-11-01 06:11:15 +08:00
endif ( )
if ( MPI_ ${ LANG } _COMPILE_DEFINITIONS )
foreach ( _MPI_DEF IN LISTS MPI_ ${ LANG } _COMPILE_DEFINITIONS )
string ( APPEND MPI_ ${ LANG } _COMPILE_FLAGS " -D${_MPI_DEF}" )
endforeach ( )
endif ( )
endif ( )
endforeach ( )
# Bare MPI sans ${LANG} vars are set to CXX then C, depending on what was found.
# This mimics the behavior of the old language-oblivious FindMPI.
set ( _MPI_OLD_VARS COMPILER INCLUDE_PATH COMPILE_FLAGS LINK_FLAGS LIBRARIES )
if ( MPI_CXX_FOUND )
foreach ( var ${ _MPI_OLD_VARS } )
set ( MPI_ ${ var } ${ MPI_CXX_${var } } )
endforeach ( )
elseif ( MPI_C_FOUND )
foreach ( var ${ _MPI_OLD_VARS } )
set ( MPI_ ${ var } ${ MPI_C_${var } } )
endforeach ( )
endif ( )
# Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and MPI_EXTRA_LIBRARY, and set them in cache.
if ( MPI_LIBRARIES )
list ( GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK )
set ( MPI_LIBRARY "${MPI_LIBRARY_WORK}" )
unset ( MPI_LIBRARY_WORK )
else ( )
set ( MPI_LIBRARY "MPI_LIBRARY-NOTFOUND" )
endif ( )
list ( LENGTH MPI_LIBRARIES MPI_NUMLIBS )
if ( MPI_NUMLIBS GREATER 1 )
set ( MPI_EXTRA_LIBRARY_WORK "${MPI_LIBRARIES}" )
list ( REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0 )
set ( MPI_EXTRA_LIBRARY "${MPI_EXTRA_LIBRARY_WORK}" )
unset ( MPI_EXTRA_LIBRARY_WORK )
else ( )
set ( MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" )
endif ( )
set ( MPI_IGNORE_LEGACY_VARIABLES TRUE )
#=============================================================================
# unset these vars to cleanup namespace
unset ( _MPI_OLD_VARS )
unset ( _MPI_PREFIX_PATH )
unset ( _MPI_BASE_DIR )
foreach ( lang C CXX Fortran )
unset ( _MPI_ ${ LANG } _COMPILER_NAMES )
endforeach ( )
cmake_policy ( POP )