@@ -61,7 +61,7 @@ func main() {
6161 force := flag .Bool ("force" , false , "re-download even if the library is already installed" )
6262 flag .Parse ()
6363
64- root , err := resolveBindingsDir (* bindingsDir )
64+ root , err := resolveWritableBindingsDir (* bindingsDir )
6565 if err != nil {
6666 fatal (err )
6767 }
@@ -81,24 +81,47 @@ func main() {
8181 }
8282
8383 for _ , p := range targets {
84- libDir , installHeader , err := resolveLibDir (root , version , p .id )
85- if err != nil {
86- fatal (err )
87- }
88- if err := installPlatform (root , libDir , installHeader , baseURL , version , p , checksums , * force ); err != nil {
84+ libDir := filepath .Join (root , "lib" , p .id )
85+ if err := installPlatform (root , libDir , true , baseURL , version , p , checksums , * force ); err != nil {
8986 fatal (fmt .Errorf ("%s: %w" , p .id , err ))
9087 }
91- if libDir != filepath .Join (root , "lib" , p .id ) {
92- printLinkerHint (p , libDir )
93- }
9488 }
9589
9690 fmt .Printf ("Installed Moss C SDK %s\n " , * releaseTag )
91+ fmt .Printf ("Native libraries installed under %s\n " , root )
92+ }
93+
94+ // resolveWritableBindingsDir returns the bindings package CGO will compile.
95+ // Downloaded Go modules are read-only, so an external consumer is vendored
96+ // before installing the native library beside the bindings source.
97+ func resolveWritableBindingsDir (explicit string ) (string , error ) {
98+ root , err := resolveBindingsDir (explicit )
99+ if err != nil {
100+ return "" , err
101+ }
102+ if isWritableDir (root ) {
103+ return root , nil
104+ }
105+ if explicit != "" || strings .TrimSpace (os .Getenv ("MOSS_BINDINGS_DIR" )) != "" {
106+ return "" , fmt .Errorf ("bindings directory %s is not writable" , root )
107+ }
108+
109+ goMod , err := goEnv ("GOMOD" )
110+ if err != nil || goMod == os .DevNull || goMod == "" {
111+ return "" , fmt .Errorf ("the downloaded bindings module is read-only; run this command from a Go module that imports the Moss SDK" )
112+ }
113+ if out , err := exec .Command ("go" , "mod" , "vendor" ).CombinedOutput (); err != nil {
114+ return "" , fmt .Errorf ("vendor Moss bindings for native installation: %w\n %s" , err , strings .TrimSpace (string (out )))
115+ }
116+
117+ root , err = bindingsDirFromGoList ("-mod=vendor" )
118+ if err != nil {
119+ return "" , fmt .Errorf ("locate vendored Moss bindings after `go mod vendor`: %w" , err )
120+ }
97121 if ! isWritableDir (root ) {
98- fmt .Println ("Build with -mod=vendor after `go mod vendor`, or export the CGO_LDFLAGS shown above." )
99- } else {
100- fmt .Printf ("Native libraries installed under %s\n " , root )
122+ return "" , fmt .Errorf ("vendored bindings directory %s is not writable" , root )
101123 }
124+ return root , nil
102125}
103126
104127func resolveBindingsDir (explicit string ) (string , error ) {
@@ -118,8 +141,10 @@ func resolveBindingsDir(explicit string) (string, error) {
118141 return filepath .Abs (filepath .Join (filepath .Dir (file ), ".." , ".." , "bindings" ))
119142}
120143
121- func bindingsDirFromGoList () (string , error ) {
122- cmd := exec .Command ("go" , "list" , "-f" , "{{.Dir}}" , bindingsModulePath )
144+ func bindingsDirFromGoList (args ... string ) (string , error ) {
145+ args = append ([]string {"list" }, args ... )
146+ args = append (args , "-f" , "{{.Dir}}" , bindingsModulePath )
147+ cmd := exec .Command ("go" , args ... )
123148 out , err := cmd .Output ()
124149 if err != nil {
125150 return "" , err
@@ -131,19 +156,6 @@ func bindingsDirFromGoList() (string, error) {
131156 return filepath .Abs (dir )
132157}
133158
134- func resolveLibDir (bindingsRoot , version , platformID string ) (string , bool , error ) {
135- inBindings := filepath .Join (bindingsRoot , "lib" , platformID )
136- if isWritableDir (bindingsRoot ) {
137- return inBindings , true , nil
138- }
139-
140- cacheRoot , err := os .UserCacheDir ()
141- if err != nil {
142- return "" , false , err
143- }
144- return filepath .Join (cacheRoot , "moss-go" , version , platformID ), false , nil
145- }
146-
147159func isWritableDir (dir string ) bool {
148160 if dir == "" {
149161 return false
@@ -156,15 +168,12 @@ func isWritableDir(dir string) bool {
156168 return true
157169}
158170
159- func printLinkerHint (p platform , libDir string ) {
160- switch p .id {
161- case "darwin-arm64" :
162- fmt .Printf ("export CGO_LDFLAGS=\" -L%s -lmoss -lc++ -framework Security -framework SystemConfiguration\" \n " , libDir )
163- case "windows-amd64" :
164- fmt .Printf ("set CGO_LDFLAGS=-L%s %s\n " , libDir , p .libFile )
165- default :
166- fmt .Printf ("export CGO_LDFLAGS=\" -L%s -lmoss -lstdc++ -ldl -lm -lpthread\" \n " , libDir )
171+ func goEnv (name string ) (string , error ) {
172+ out , err := exec .Command ("go" , "env" , name ).Output ()
173+ if err != nil {
174+ return "" , err
167175 }
176+ return strings .TrimSpace (string (out )), nil
168177}
169178
170179func selectPlatforms (all bool ) ([]platform , error ) {
0 commit comments