Commit fb59aed6 authored by Russ Cox's avatar Russ Cox

cmd/cgo: split cgo_export into cgo_export_static and cgo_export_dynamic

Also emit cgo_ldflag pragmas.

R=golang-dev, remyoudompheng, iant
CC=golang-dev
https://golang.org/cl/7530043
parent 56d1faa8
......@@ -692,22 +692,24 @@ pragcgo(char *verb)
goto out;
}
if(strcmp(verb, "cgo_export") == 0 || strcmp(verb, "dynexport") == 0) {
if(strcmp(verb, "dynexport") == 0)
verb = "cgo_export_dynamic";
if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
local = getimpsym();
if(local == nil)
goto err2;
if(!more()) {
fmtprint(&pragcgobuf, "cgo_export %q\n", local->name);
fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
goto out;
}
remote = getimpsym();
if(remote == nil)
goto err2;
fmtprint(&pragcgobuf, "cgo_export %q %q\n", local->name, remote->name);
fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
goto out;
err2:
yyerror("usage: #pragma cgo_export local [remote]");
yyerror("usage: #pragma %s local [remote]", verb);
goto out;
}
......@@ -749,6 +751,18 @@ pragcgo(char *verb)
goto out;
}
if(strcmp(verb, "cgo_ldflag") == 0) {
p = getquoted();
if(p == nil)
goto err5;
fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
goto out;
err5:
yyerror("usage: #pragma cgo_ldflag \"arg\"");
goto out;
}
out:
while(getnsc() != '\n')
;
......
......@@ -484,16 +484,16 @@ The directives are:
Example:
#pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
#pragma cgo_export <local> <remote>
#pragma cgo_export_dynamic <local> <remote>
In both internal and external linking modes, put the Go symbol
In internal linking mode, put the Go symbol
named <local> into the program's exported symbol table as
<remote>, so that C code can refer to it by that name. This
mechanism makes it possible for C code to call back into Go or
to share Go's data.
For compatibility with current versions of SWIG,
#pragma dynexport is an alias for #pragma cgo_export.
#pragma dynexport is an alias for #pragma cgo_export_dynamic.
#pragma cgo_import_static <local>
......@@ -505,6 +505,14 @@ The directives are:
Example:
#pragma cgo_import_static puts_wrapper
#pragma cgo_export_static <local> <remote>
In external linking mode, put the Go symbol
named <local> into the program's exported symbol table as
<remote>, so that C code can refer to it by that name. This
mechanism makes it possible for C code to call back into Go or
to share Go's data.
#pragma cgo_ldflag "<arg>"
In external linking mode, invoke the host linker (usually gcc)
......
......@@ -139,11 +139,7 @@ NextLine:
// addToFlag appends args to flag. All flags are later written out onto the
// _cgo_flags file for the build system to use.
func (p *Package) addToFlag(flag string, args []string) {
if oldv, ok := p.CgoFlags[flag]; ok {
p.CgoFlags[flag] = oldv + " " + strings.Join(args, " ")
} else {
p.CgoFlags[flag] = strings.Join(args, " ")
}
p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
if flag == "CFLAGS" {
// We'll also need these when preprocessing for dwarf information.
p.GccOptions = append(p.GccOptions, args...)
......
......@@ -33,7 +33,7 @@ type Package struct {
PtrSize int64
IntSize int64
GccOptions []string
CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS)
CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
Written map[string]bool
Name map[string]*Name // accumulated Name from Files
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
......@@ -312,7 +312,7 @@ func newPackage(args []string) *Package {
PtrSize: ptrSize,
IntSize: intSize,
GccOptions: gccOptions,
CgoFlags: make(map[string]string),
CgoFlags: make(map[string][]string),
Written: make(map[string]bool),
}
return p
......
......@@ -31,7 +31,12 @@ func (p *Package) writeDefs() {
fflg := creat(*objDir + "_cgo_flags")
for k, v := range p.CgoFlags {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
if k == "LDFLAGS" {
for _, arg := range v {
fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
}
}
}
fflg.Close()
......@@ -100,6 +105,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
cVars[n.C] = true
......@@ -651,8 +657,9 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
fmt.Fprintf(fc, "#pragma cgo_export %s\n", goname)
fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
......
......@@ -487,7 +487,9 @@ loadcgo(char *file, char *pkg, char *p, int n)
continue;
}
if(strcmp(f[0], "cgo_export") == 0) {
// TODO: cgo_export_static
if(strcmp(f[0], "cgo_export_dynamic") == 0) {
if(nf < 2 || nf > 3)
goto err;
local = f[1];
......@@ -501,13 +503,17 @@ loadcgo(char *file, char *pkg, char *p, int n)
fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
nerrors++;
}
s->dynimpname = remote;
s->dynexport = 1;
if(ndynexp%32 == 0)
dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
dynexp[ndynexp++] = s;
if(s->dynimpname == nil) {
s->dynimpname = remote;
if(ndynexp%32 == 0)
dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
dynexp[ndynexp++] = s;
} else if(strcmp(s->dynimpname, remote) != 0) {
fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->dynimpname, remote);
nerrors++;
return;
}
if(local != f[1])
free(local);
continue;
......@@ -528,6 +534,15 @@ loadcgo(char *file, char *pkg, char *p, int n)
}
continue;
}
if(strcmp(f[0], "cgo_ldflag") == 0) {
if(nf != 2)
goto err;
if(nldflag%32 == 0)
ldflag = realloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
ldflag[nldflag++] = strdup(f[1]);
continue;
}
}
free(p0);
return;
......
......@@ -138,6 +138,8 @@ EXTERN char* outfile;
EXTERN int32 nsymbol;
EXTERN char* thestring;
EXTERN int ndynexp;
EXTERN int nldflag;
EXTERN char** ldflag;
EXTERN int havedynamic;
EXTERN int iscgo;
EXTERN int isobj;
......
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