33from conan .tools .layout import basic_layout
44from conan .errors import ConanInvalidConfiguration
55from conan .tools .gnu import Autotools , AutotoolsToolchain
6+ from conan .tools .env import VirtualBuildEnv
67
78import os
9+ import shlex
10+
811
912class AmneziaXrayBindings (ConanFile ):
1013 name = "amnezia-xray-bindings"
1114 version = "1.1.0"
1215 settings = "os" , "arch" , "compiler"
16+ _lib_name = "libamnezia_xray.a"
1317
1418 @property
1519 def _goos (self ):
@@ -19,15 +23,108 @@ def _goos(self):
1923 "Macos" : "darwin" ,
2024 "Windows" : "windows"
2125 }.get (str (self .settings .os ))
22-
26+
2327 @property
24- def _goarch (self ):
28+ def _arch_map (self ):
2529 return {
2630 "x86" : "386" ,
2731 "x86_64" : "amd64" ,
2832 "armv8" : "arm64"
29- }.get (str (self .settings .arch ))
30-
33+ }
34+
35+ @property
36+ def _apple_arch_map (self ):
37+ return {
38+ "x86_64" : "x86_64" ,
39+ "armv8" : "arm64" ,
40+ }
41+
42+ @property
43+ def _archs (self ):
44+ return str (self .settings .arch ).split ("|" )
45+
46+ @property
47+ def _goarch (self ):
48+ goarchs = [self ._arch_map .get (arch ) for arch in self ._archs ]
49+ return goarchs [0 ] if len (goarchs ) == 1 else None
50+
51+ @property
52+ def _goarchs (self ):
53+ return [self ._arch_map .get (arch ) for arch in self ._archs ]
54+
55+ @property
56+ def _is_universal_macos (self ):
57+ return str (self .settings .os ) == "Macos" and len (self ._archs ) > 1
58+
59+ @property
60+ def _is_unsupported_multi_arch (self ):
61+ return len (self ._archs ) > 1 and not self ._is_universal_macos
62+
63+ def _go_cache_vars (self ):
64+ return {
65+ "GOPATH" : os .path .join (self .build_folder , "gopath" ),
66+ "GOMODCACHE" : os .path .join (self .build_folder , "gopath" , "pkg" , "mod" ),
67+ "GOCACHE" : os .path .join (self .build_folder , "gocache" ),
68+ "GOTELEMETRY" : "off" ,
69+ }
70+
71+ def _define_go_cache_env (self , env ):
72+ for name , value in self ._go_cache_vars ().items ():
73+ env .define (name , value )
74+
75+ def _go_cache_make_args (self ):
76+ return [f"{ name } ={ value } " for name , value in self ._go_cache_vars ().items ()]
77+
78+ def _non_arch_flags (self , flags ):
79+ tokens = []
80+ for flag in flags :
81+ tokens .extend (shlex .split (flag ))
82+
83+ result = []
84+ skip_next = False
85+ for flag in tokens :
86+ if skip_next :
87+ skip_next = False
88+ elif flag == "-arch" :
89+ skip_next = True
90+ else :
91+ result .append (flag )
92+ return result
93+
94+ def _cgo_flags (self , arch , flags ):
95+ return " " .join (["-arch" , self ._apple_arch_map [arch ]] + self ._non_arch_flags (flags ))
96+
97+ def _make_var (self , name , value ):
98+ return f"{ name } ={ shlex .quote (value )} "
99+
100+ def _go_arch_make_args (self , arch , goarch ):
101+ tc = AutotoolsToolchain (self )
102+ return self ._go_cache_make_args () + [
103+ f"GOOS={ self ._goos } " ,
104+ f"GOARCH={ goarch } " ,
105+ f"ARCH={ goarch } " ,
106+ self ._make_var ("CGO_CFLAGS" , self ._cgo_flags (arch , tc .cflags )),
107+ self ._make_var ("CGO_LDFLAGS" , self ._cgo_flags (arch , tc .ldflags )),
108+ ]
109+
110+ def _build_go_arch (self , arch , goarch ):
111+ with chdir (self , self .source_folder ):
112+ autotools = Autotools (self )
113+ autotools .make (args = self ._go_arch_make_args (arch , goarch ))
114+
115+ output_path = os .path .join (self .build_folder , self ._lib_name )
116+ if not os .path .exists (output_path ):
117+ output_path = os .path .join (self .source_folder , self ._lib_name )
118+
119+ arch_output_path = os .path .join (self .build_folder , f"libamnezia_xray-{ goarch } .a" )
120+ os .rename (output_path , arch_output_path )
121+ return arch_output_path
122+
123+ def _build_universal_macos (self ):
124+ outputs = [self ._build_go_arch (arch , goarch ) for arch , goarch in zip (self ._archs , self ._goarchs )]
125+ universal_output = os .path .join (self .build_folder , self ._lib_name )
126+ self .run (f"lipo -create { ' ' .join (outputs )} -output { universal_output } " )
127+
31128 @property
32129 def _is_windows (self ):
33130 return str (self .settings .os ).startswith ("Windows" )
@@ -54,7 +151,7 @@ def build_requirements(self):
54151 self .tool_requires ("mingw-builds/15.1.0" )
55152
56153 def validate (self ):
57- if not self ._goos or not self ._goarch :
154+ if not self ._goos or not all ( self ._goarchs ) or self . _is_unsupported_multi_arch :
58155 raise ConanInvalidConfiguration (
59156 f"{ self .name } v{ self .version } does not support { self .settings .os } { self .settings .arch } "
60157 )
@@ -64,21 +161,28 @@ def source(self):
64161 sha256 = "6ea768ec7002cedd422a39aea17704b888acaf794432aa5937cfc92fb6d80eb5" , strip_root = True )
65162
66163 def generate (self ):
164+ VirtualBuildEnv (self ).generate ()
67165 tc = AutotoolsToolchain (self )
68166 tc .make_args = [
69167 "LIB_ARC=libamnezia_xray.a"
70168 ]
71169 env = tc .environment ()
72- env .define ("ARCH" , self ._goarch )
73- env .define ("GOARCH" , self ._goarch )
170+ self ._define_go_cache_env (env )
171+ if not self ._is_universal_macos :
172+ env .define ("ARCH" , self ._goarch )
173+ env .define ("GOARCH" , self ._goarch )
174+ env .define ("CGO_LDFLAGS" , tc .ldflags )
175+ env .define ("CGO_CFLAGS" , tc .cflags )
74176 env .define ("GOOS" , self ._goos )
75- env .define ("CGO_LDFLAGS" , tc .ldflags )
76- env .define ("CGO_CFLAGS" , tc .cflags )
77177 if self ._is_windows :
78178 env .define ("OS" , "windows" )
79179 tc .generate (env )
80180
81181 def build (self ):
182+ if self ._is_universal_macos :
183+ self ._build_universal_macos ()
184+ return
185+
82186 with chdir (self , self .source_folder ):
83187 autotools = Autotools (self )
84188 autotools .make ()
@@ -100,7 +204,10 @@ def _rename_libs(self):
100204
101205 def package (self ):
102206 copy (self , "*.h" , src = self .build_folder , dst = os .path .join (self .package_folder , "include" ))
103- copy (self , "*.a" , src = self .build_folder , dst = os .path .join (self .package_folder , "lib" ))
207+ if self ._is_universal_macos :
208+ copy (self , self ._lib_name , src = self .build_folder , dst = os .path .join (self .package_folder , "lib" ))
209+ else :
210+ copy (self , "*.a" , src = self .build_folder , dst = os .path .join (self .package_folder , "lib" ))
104211 copy (self , "*.lib" , src = self .build_folder , dst = os .path .join (self .package_folder , "lib" ))
105212 copy (self , "*.dll" , src = self .build_folder , dst = os .path .join (self .package_folder , "bin" ))
106213 self ._rename_header ()
0 commit comments