Commit 489494ca authored by Russ Cox's avatar Russ Cox

cgo: use slash-free relative paths for .so references

The Makefile and cgo now rewrite / to _ when creating the path.
The .so for gosqlite.googlecode.com/hg/sqlite is named
cgo_gosqlite.googlecode.com_hg_sqlite.so, and then 6l and 8l
both include a default rpath of $GOROOT/pkg/$GOOS_$GOARCH.
This should make it easier to move binaries from one system
to another.

Fixes #857.

R=iant, r
CC=golang-dev
https://golang.org/cl/1700048
parent 7c9ed794
...@@ -31,11 +31,12 @@ INSTALLFILES+=$(pkgdir)/$(TARG).a ...@@ -31,11 +31,12 @@ INSTALLFILES+=$(pkgdir)/$(TARG).a
# The rest of the cgo rules are below, but these variable updates # The rest of the cgo rules are below, but these variable updates
# must be done here so they apply to the main rules. # must be done here so they apply to the main rules.
ifdef CGOFILES ifdef CGOFILES
CGOTARG=cgo_$(subst /,_,$(TARG))
GOFILES+=$(patsubst %.go,%.cgo1.go,$(CGOFILES)) GOFILES+=$(patsubst %.go,%.cgo1.go,$(CGOFILES))
GOFILES+=_cgo_gotypes.go GOFILES+=_cgo_gotypes.go
OFILES+=_cgo_defun.$O OFILES+=_cgo_defun.$O
GCC_OFILES=$(patsubst %.go,%.cgo2.o,$(CGOFILES)) GCC_OFILES=$(patsubst %.go,%.cgo2.o,$(CGOFILES))
INSTALLFILES+=$(pkgdir)/$(TARG).so INSTALLFILES+=$(pkgdir)/$(CGOTARG).so
endif endif
PREREQ+=$(patsubst %,%.make,$(DEPS)) PREREQ+=$(patsubst %,%.make,$(DEPS))
...@@ -146,7 +147,7 @@ _cgo_defun.$O: _cgo_defun.c ...@@ -146,7 +147,7 @@ _cgo_defun.$O: _cgo_defun.c
_cgo_.so: $(GCC_OFILES) $(CGO_DEPS) _cgo_.so: $(GCC_OFILES) $(CGO_DEPS)
gcc $(_CGO_CFLAGS_$(GOARCH)) -o $@ $(GCC_OFILES) $(CGO_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) gcc $(_CGO_CFLAGS_$(GOARCH)) -o $@ $(GCC_OFILES) $(CGO_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS))
$(pkgdir)/$(TARG).so: _cgo_.so $(pkgdir)/$(CGOTARG).so: _cgo_.so
@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir) @test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir)
cp _cgo_.so "$@" cp _cgo_.so "$@"
......
...@@ -146,6 +146,8 @@ main(int argc, char *argv[]) ...@@ -146,6 +146,8 @@ main(int argc, char *argv[])
usage(); usage();
libinit(); libinit();
if(rpath == nil)
rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
if(!debug['9'] && !debug['U'] && !debug['B']) if(!debug['9'] && !debug['U'] && !debug['B'])
debug[DEFAULT] = 1; debug[DEFAULT] = 1;
......
...@@ -138,6 +138,8 @@ main(int argc, char *argv[]) ...@@ -138,6 +138,8 @@ main(int argc, char *argv[])
usage(); usage();
libinit(); libinit();
if(rpath == nil)
rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
if(HEADTYPE == -1) { if(HEADTYPE == -1) {
HEADTYPE = 2; HEADTYPE = 2;
......
...@@ -175,6 +175,8 @@ main(int argc, char *argv[]) ...@@ -175,6 +175,8 @@ main(int argc, char *argv[])
} }
libinit(); libinit();
if(rpath == nil)
rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
switch(HEADTYPE) { switch(HEADTYPE) {
default: default:
......
...@@ -21,6 +21,13 @@ func creat(name string) *os.File { ...@@ -21,6 +21,13 @@ func creat(name string) *os.File {
return f return f
} }
func slashToUnderscore(c int) int {
if c == '/' {
c = '_'
}
return c
}
// writeDefs creates output files to be compiled by 6g, 6c, and gcc. // writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Prog) writeDefs() { func (p *Prog) writeDefs() {
...@@ -30,6 +37,15 @@ func (p *Prog) writeDefs() { ...@@ -30,6 +37,15 @@ func (p *Prog) writeDefs() {
path = pkgroot + "/" + path path = pkgroot + "/" + path
} }
// The path for the shared object is slash-free so that ELF loaders
// will treat it as a relative path. We rewrite slashes to underscores.
sopath := "cgo_" + strings.Map(slashToUnderscore, p.PackagePath)
soprefix := ""
if os.Getenv("GOOS") == "darwin" {
// OS X requires its own prefix for a relative path
soprefix = "@rpath/"
}
fgo2 := creat("_cgo_gotypes.go") fgo2 := creat("_cgo_gotypes.go")
fc := creat("_cgo_defun.c") fc := creat("_cgo_defun.c")
...@@ -48,10 +64,10 @@ func (p *Prog) writeDefs() { ...@@ -48,10 +64,10 @@ func (p *Prog) writeDefs() {
} }
fmt.Fprintf(fgo2, "type _C_void [0]byte\n") fmt.Fprintf(fgo2, "type _C_void [0]byte\n")
fmt.Fprintf(fc, cProlog, pkgroot, pkgroot, pkgroot, pkgroot, pkgroot) fmt.Fprintf(fc, cProlog, soprefix, soprefix, soprefix, soprefix, soprefix)
for name, def := range p.Vardef { for name, def := range p.Vardef {
fmt.Fprintf(fc, "#pragma dynimport ·_C_%s %s \"%s.so\"\n", name, name, path) fmt.Fprintf(fc, "#pragma dynimport ·_C_%s %s \"%s%s.so\"\n", name, name, soprefix, sopath)
fmt.Fprintf(fgo2, "var _C_%s ", name) fmt.Fprintf(fgo2, "var _C_%s ", name)
printer.Fprint(fgo2, &ast.StarExpr{X: def.Go}) printer.Fprint(fgo2, &ast.StarExpr{X: def.Go})
fmt.Fprintf(fgo2, "\n") fmt.Fprintf(fgo2, "\n")
...@@ -130,7 +146,7 @@ func (p *Prog) writeDefs() { ...@@ -130,7 +146,7 @@ func (p *Prog) writeDefs() {
// C wrapper calls into gcc, passing a pointer to the argument frame. // C wrapper calls into gcc, passing a pointer to the argument frame.
// Also emit #pragma to get a pointer to the gcc wrapper. // Also emit #pragma to get a pointer to the gcc wrapper.
fmt.Fprintf(fc, "#pragma dynimport _cgo_%s _cgo_%s \"%s.so\"\n", name, name, path) fmt.Fprintf(fc, "#pragma dynimport _cgo_%s _cgo_%s \"%s%s.so\"\n", name, name, soprefix, sopath)
fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name) fmt.Fprintf(fc, "void (*_cgo_%s)(void*);\n", name)
fmt.Fprintf(fc, "\n") fmt.Fprintf(fc, "\n")
fmt.Fprintf(fc, "void\n") fmt.Fprintf(fc, "void\n")
...@@ -564,11 +580,11 @@ const cProlog = ` ...@@ -564,11 +580,11 @@ const cProlog = `
#include "runtime.h" #include "runtime.h"
#include "cgocall.h" #include "cgocall.h"
#pragma dynimport initcgo initcgo "%s/libcgo.so" #pragma dynimport initcgo initcgo "%slibcgo.so"
#pragma dynimport libcgo_thread_start libcgo_thread_start "%s/libcgo.so" #pragma dynimport libcgo_thread_start libcgo_thread_start "%slibcgo.so"
#pragma dynimport libcgo_set_scheduler libcgo_set_scheduler "%s/libcgo.so" #pragma dynimport libcgo_set_scheduler libcgo_set_scheduler "%slibcgo.so"
#pragma dynimport _cgo_malloc _cgo_malloc "%s/libcgo.so" #pragma dynimport _cgo_malloc _cgo_malloc "%slibcgo.so"
#pragma dynimport _cgo_free _cgo_free "%s/libcgo.so" #pragma dynimport _cgo_free _cgo_free "%slibcgo.so"
void void
·_C_GoString(int8 *p, String s) ·_C_GoString(int8 *p, String s)
......
...@@ -441,6 +441,7 @@ asmbmacho(vlong symdatva, vlong symo) ...@@ -441,6 +441,7 @@ asmbmacho(vlong symdatva, vlong symo)
vlong v, w; vlong v, w;
vlong va; vlong va;
int a, i, ptrsize; int a, i, ptrsize;
char *pkgroot;
MachoHdr *mh; MachoHdr *mh;
MachoSect *msect; MachoSect *msect;
MachoSeg *ms; MachoSeg *ms;
...@@ -584,6 +585,12 @@ asmbmacho(vlong symdatva, vlong symo) ...@@ -584,6 +585,12 @@ asmbmacho(vlong symdatva, vlong symo)
ml->data[0] = 12; /* offset to string */ ml->data[0] = 12; /* offset to string */
strcpy((char*)&ml->data[1], "/usr/lib/dyld"); strcpy((char*)&ml->data[1], "/usr/lib/dyld");
if(ndylib > 0) { /* add reference to where .so files are installed */
pkgroot = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
ml = newMachoLoad(0x80000000 | 0x1c, 1+(strlen(pkgroot)+1+7)/8*2); /* LC_RPATH */
ml->data[0] = 12; /* offset of string from beginning of load */
strcpy((char*)&ml->data[1], pkgroot);
}
for(i=0; i<ndylib; i++) { for(i=0; i<ndylib; i++) {
ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */ ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
ml->data[0] = 24; /* offset of string from beginning of load */ ml->data[0] = 24; /* offset of string from beginning of load */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment